collection_select question

Hello,

I'm pretty new to Ruby on Rails (ROR) so I'm sorry if this is a silly
thing to ask. I have tried looking at several tutorials online but
most of them are for the earlier version of ROR and even the API is
not helping me too much!

Basically I would like to create a drop down list in a form. I have
simplified my problem so that you'll be able to understand it in a few
lines.

A simple diagram is here:
http://learningspirit.co.uk/class_diagram.png

The migration and model files are here:
## db/migrate/003_books.rb
class Books < ActiveRecord::Migration
  def self.up
    create_table :books do |t|
      t.column :title, :string, :limit => 32, :null => false
      t.column :price, :float
      t.column :subject_id, :integer
      t.column :description, :text
      t.column :created_at, :timestamp
    end
  end

  def self.down
    drop_table :books
  end
end

## db/migrate/004_subjects.rb
class Subjects < ActiveRecord::Migration
  def self.up
    create_table :subjects do |t|
      t.column :name, :string
    end

    Subject.create :name => "Physics"
    Subject.create :name => "Mathematics"
    Subject.create :name => "Chemistry"
    Subject.create :name => "Psychology"
    Subject.create :name => "Geography"
  end

  def self.down
    drop_table :subjects
  end
end

## app/model/book.rb
class Book < ActiveRecord::Base
  belongs_to :subject
  validates_presence_of :title
  validates_numericality_of :price, :message=>"Error message"
end

## app/model/subject.rb
class Subject < ActiveRecord::Base
  has_many :books
end

The relevant book_controller.rb methods are:
  def new
    @book = Book.new
    @subjects = Subject.find(:all)
  end

  def create
    @book = Book.new(params[:book])
    if @book.save
      redirect_to :action => 'list'
    else
      @subjects = Subject.find(:all)
      render :action => 'new'
    end
  end

The problem I have is in the view for the form to create a new book
entry. The view (app/views/book/new.html.erb) is looking like this at
the moment:

<h1>Add new book</h1>
<% form_for :book, @book, :url => { :action => "create" } do |f| %>
<p>
<label>Title</label>:
<%= text_field @book, :title %>
</p>
<p>
<label>Price</label>:
<%= text_field @book, :price %>
</p>
<p>
<label>Subject</label>:
<%= collection_select :book, :subject_id, @subjects, :id, :name %>
</p>
<p>
<label>Description</label>:
<%= text_area @book, :description %>
</p>
<p>
<%= f.submit "Create"%>
</p>
<% end %>
<%= link_to 'Back', {:action => 'list'} %>

My problem is that I cannot get the drop down list to work! I have
tried select (instead of collection_sort) but I am always getting
errors. At the moment I have the following error:

undefined method `subject_id' for #<Book id: nil, created_at: nil,
updated_at: nil>

I don't understand this at all because from the documentation, there
should be a method there!

Please could some help me? What exactly are the arguments for the
collection_select method? What is wrong with my collection_select
call?

Thank you very much and I hope this wasn't too long winded!
Inuka.

Did you change a migration after having run it (for example to add
subject_id to the books table). Rails won't notice if you do that. You
either need to create a new migration when you want a changed like
that or you need to migrate down and then up again.

Fred

Hi,
So you're on here too huh?

I think the problem is you're trying to access the subject model from
within the book model...so rails is not gonna understand what
subject_id is and is therefore probably looking for a method by that
name which doesn't exist.

I haven't tried this out myself yet but I think this might help you:
http://railscasts.com/episodes/73

Thank you for the replies!

It turns out that there were many problems with my form. I fixed them
and it is pasted below in case it will be of some use to someone else
having problems with collection_sort!

% if flash[:notice] %>
  <%= flash[:notice] %>
<% end %>

<h1>Add new book</h1>
<% form_for :book, @book, :url => { :action => "create" } do |f| %>
<p>
Title:
<%= f.text_field :title %>
</p>

<p>
Price:
<%= f.text_field :price %>
</p>

<p>
Subject:
<%= f.collection_select :subject_id, @subjects, :id, :name %>
</p>

<p>
Description:
<%= f.text_area :description %>
</p>

<p>
<%= f.submit "Create"%>
</p>

<% end %>

<%= link_to 'Back', {:action => 'list'} %>

Thank you.