Am I going too far or Rails is just confusing? was {validate

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’ %>

Name
<%= text_field 'customer', 'name' %>

Phone
<%= text_field 'customer', 'phone' %>

Address
<%= text_field 'customer', 'address' %>

Rank
<%= select 'customer', 'rank', Rank.find_all.collect { |r| [ r.description, r.id ] } %>

  1. 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!!!

  1. 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!!!

  1. 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

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

Rank
<%= select 'customer', 'rank_id', Rank.find_all.collect { |r| [ r.description, r.id ] } %>

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

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

Rank
<%= select 'customer', 'rank', Rank.find_all.collect { |r| [ r.description, r.id ] } %>

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.

Hello John !

2006/1/3, John I. [email protected]:

Rank
<%= select 'customer', 'rank', Rank.find_all.collect { |r| [ r.description, r.id ] } %>

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/belongs_to-user-interface-take-ii

The gist of the article was this:

Rank
<%= collection_select 'customer', 'rank', Rank.find(:all), :id, :name %>

Hope that helps !

On 1/4/06, Francois B. [email protected] wrote:

http://blog.teksol.info/articles/2006/01/03/belongs_to-user-interface-take-ii

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:

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

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.

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] Peak Obsession
ActiveRecordHelper.html#M000371

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