Forum: Ruby on Rails Am I going too far or Rails is just confusing? was {validate

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
John I. (Guest)
on 2006-01-03 22:28
(Received via mailing list)
Thanks for the input Blair Z. and Chris (Nolan and Hall), and for
others.

If all of  you have time, please follow this (the question still
relates to the previous posts by me):

I have provided full steps to reproduce the symptoms.
If it matters, I'm running Ruby 1.8.2, Rails 1.0, and MySQL 5.0.15 on
Windows XP Professional.

1. First, the setup

MySQL
-----
create database testdb;

create table ranks (id tinyint unsigned not null auto_increment,
description varchar(50) not null unique, primary key(id));

create table customers (id mediumint unsigned not null auto_increment,
name varchar(50) not null,
phone varchar(25), address varchar(50), rank_id tinyint unsigned not
null, primary key(id),
foreign key (rank_id) references ranks(id));

Leave the tables blank. This is intentional.

Rails
-----
> rails myapp
> cd myapp
> ruby script\server
> ruby script\generate scaffold rank 'admin/ranks'
> ruby script\generate scaffold customer 'admin/customers'

Edit the models
---------------
app/models/rank.rb:
class Rank < ActiveRecord::Base
  has_many :customers
  validates_presence_of :description
  validates_length_of :description, :maximum => 50
  validates_uniqueness_of :description
end

app/models/customer.rb:
class Customer < ActiveRecord::Base
  belongs_to :rank
  validates_presence_of :name
  validates_length_of :name, :maximum => 50
  validates_presence_of :rank
  validates_associated :rank
end

Edit app/views/admin/customers/_form.html
-----------------------------------------
<%= error_messages_for 'customer' %>

<!--[form:customer]-->
<p><label for="customer_name">Name</label><br />
<%= text_field 'customer', 'name'  %></p>

<p><label for="customer_phone">Phone</label><br />
<%= text_field 'customer', 'phone'  %></p>

<p><label for="customer_address">Address</label><br />
<%= text_field 'customer', 'address'  %></p>

<p><label for="customer_rank">Rank</label><br />
<%= select 'customer', 'rank', Rank.find_all.collect { |r| [
r.description, r.id ] } %></p>

<!--[eoform:customer]-->

2. Let's try

Go to http://localhost:3000/admin/customers/new
Then just press the "Create" button
Rails responds:

2 errors prohibited this customer from being saved

There were problems with the following fields:

    * Name can't be blank
    * Rank can't be blank

The name textbox and the rank select field are highlighted with red.

SMART!!!

3. Try this then
Still at http://localhost:3000/admin/customers/new
Fill the name with whatever you want, then press the "Create" button
Rails responds:

1 error prohibited this customer from being saved

There were problems with the following fields:

    * Rank can't be blank

The rank select field is the only one highlighted with red.

I LOVE RAILS!!!

4. O O, what gives?
Head to http://localhost:3000/admin/ranks/new
Type in whatever description u want, and press the "Create" button
If all is OK, you will have 1 rank already in the ranks table.

Go back to http://localhost:3000/admin/customers/new
Now the rank select field will contain 1 option

Without typing anything, just press the "Create" button.
Oh my God, I don't understand this:
Rails responds:
ActiveRecord::AssociationTypeMismatch in Admin/customers#create

Rank expected, got String

5. What I have tried
Don't give up first John, try changing file
app/views/admin/customers/_form.html line #13-14 with:

<p><label for="customer_rank_id">Rank</label><br />
<%= select 'customer', 'rank_id', Rank.find_all.collect { |r| [
r.description, r.id ] } %></p>

Then change app/models/customer.rb line #5-6 with these:

validates_presence_of :rank_id
validates_associated :rank_id

Rush to http://localhost:3000/admin/customers/new
Don't type anything, just press "Create".
Rails bombs:

NoMethodError in Admin/customers#create

undefined method `valid?' for 4:Fixnum

No good.
I go to MySQL and issue delete from ranks;
Back to initial setup, no records at all.

Go to http://localhost:3000/admin/customers and click on "New customer"
Rails produces same error as before "undefined method `valid?' for
0:Fixnum"

What happened? What's the best way to get rid of "Rank expected, got
String" kind of error.
I understand that Ruby is searching for object of class Rank but it
faces a String.
How to overcome the problem?

Sorry for the long and so newbie e-mail. Pardon my English too. Tq so
very much,
John
Kevin O. (Guest)
on 2006-01-03 22:39
> create table customers (id mediumint unsigned not null auto_increment,
> name varchar(50) not null,
> phone varchar(25), address varchar(50), rank_id tinyint unsigned not
> null, primary key(id),
> foreign key (rank_id) references ranks(id));

>
> Edit app/views/admin/customers/_form.html
> -----------------------------------------
> <p><label for="customer_rank">Rank</label><br />
> <%= select 'customer', 'rank', Rank.find_all.collect { |r| [
> r.description, r.id ] } %></p>
>
> <!--[eoform:customer]-->

I think your problem is that the form is setting the 'rank' attribute
but your table is expecting a 'rank_id' attribute.  Try changing the
'rank' in the select to 'rank_id'and have your model validate against
:rank_id instead of :rank.
Francois B. (Guest)
on 2006-01-03 22:53
(Received via mailing list)
Hello John !

2006/1/3, John I. <removed_email_address@domain.invalid>:
> <p><label for="customer_rank">Rank</label><br />
> <%= select 'customer', 'rank', Rank.find_all.collect { |r| [
> r.description, r.id ] } %></p>

You should investigate using collection_select.  In fact, I just
updated my blog today with a new article about this:
http://blog.teksol.info/articles/2006/01/03/belong...

The gist of the article was this:
<p><label for="customer_rank">Rank</label><br />
<%= collection_select 'customer', 'rank', Rank.find(:all), :id, :name
%></p>

Hope that helps !
Wilson B. (Guest)
on 2006-01-04 02:40
(Received via mailing list)
>Then change app/models/customer.rb line #5-6 with these:
>
>validates_presence_of :rank_id
>validates_associated :rank_id

That should be:
validates_presence_of :rank_id
validates_associated :rank

Also, I don't use MySQL, but doesn't Rails treat "tinyint" values as
booleans, when using that adapter?
I would go back and make all of my "id" columns real deal integers,
rather than tinyint, mediumint, etc.
John I. (Guest)
on 2006-01-04 08:20
(Received via mailing list)
On 1/4/06, Francois B. <removed_email_address@domain.invalid> wrote:

> http://blog.teksol.info/articles/2006/01/03/belong...

I have read your article. Nice one really. Thanks a lot.

However, it doesn't work for me. Following your article, I change my
app/views/admin/customers/_form.rhtml to:
<div class="<%= 'fieldWithErrors' if error_messages_on 'customer',
'rank' %>"
<%= collection_select 'customer', 'rank_id', Rank.find_all, 'id',
'description' %></div></p>

and when I head to http://localhost:3000/admin/customers/new, Rails
bombs with this message:

NoMethodError in Admin/customers#new

Showing app/views/admin/customers/_form.rhtml where line #14 raised:

undefined method `error_messages_on' for #<#<Class:0x39acc60>:0x39acb88>

Doh!

How come an error_messages_on is not defined?

John
John I. (Guest)
on 2006-01-04 08:41
Kevin O. wrote:
> I think your problem is that the form is setting the 'rank' attribute
> but your table is expecting a 'rank_id' attribute.  Try changing the
> 'rank' in the select to 'rank_id'and have your model validate against
> :rank_id instead of :rank.

If you read my post carefully, you can tell that I've already tried
that.

Still, it doesn't work.

Tq,
John
Jarkko L. (Guest)
on 2006-01-04 13:57
(Received via mailing list)
On 4.1.2006, at 8.16, John I. wrote:
> Doh!
>
> How come an error_messages_on is not defined?

There is no such function. There's error_message_on and
error_messages_for. You're looking for the former. You can check
things like this easily from the Rails api [1].

//jarkko

[1] http://api.rubyonrails.com/classes/ActionView/Helpers/
ActiveRecordHelper.html#M000371
This topic is locked and can not be replied to.