Drop down list ?

Hi Gurus, I'm trying to tackle a drop down list. I have category and item dbs, and they're wired up with category has_many :items and item belongs_to :category, and an item has a category_id. I have this code in my new/edit.html.erb for item:

<%= f.collection_select :category_id, Category.find_main, :id, :header, {}, :multiple => false %>

And a pretty drop down list comes up, but no matter what I do, I can't save an item with a different category--it always stubbornly records the same one (or doesn't change it at all). The source html code generated is:

<select id="item_category_id" name="item[category_id]"><option value="3">Awesome Things</option> <option value="1" selected="selected">Good Things</option> <option value="2">Better Things</option></select>

...and although I can "choose" a different category for an item than 'Good Things', it only records 'Good Things' (category_id 1) for all items.

Any ideas what the problem could be here?

Many TIA, Craig

The first thing to do is to look in your log file (log/developent.log) to check that the selection is being passed in params. If it is then consider whether what the controller action that you are passing it to is doing with it.

Colin

Thanks super, Colin--that really helps. I believe category_id is being passed, as in the development.log

Processing ItemsController#update (for ::1 at 2009-09-25 06:34:23) [PUT]   Parameters: {"commit"=>"Update", ... "id"=>"228", "item"=> {..."category_id"=>["2"], ...}}   e[4;35;1mPage Load (1.1ms)e[0m e[0mSELECT * FROM "pages" ORDER BY positione[0m   e[4;36;1mUser Load (0.6ms)e[0m e[0;1mSELECT * FROM "users" WHERE ("users"."id" = 1) LIMIT 1e[0m   e[4;35;1mItem Load (0.7ms)e[0m e[0mSELECT * FROM "items" WHERE ("items"."id" = 228) e[0m Redirected to http://localhost:3000/items/228 Completed in 102ms (DB: 2) | 302 Found [http://localhost/items/228\]

and for different updates, the number in category_id is changing. In my controller, I have the provided boilerplate for update:

  def update     @item = Item.find( params[ :id ] )

    respond_to do |format|       if @item.update_attributes(params[:item]) ...

Am I missing something in the controller? Does a collection need to be handled separately?

Many TIA, Craig

Thanks super, Colin--that really helps. I believe category_id is being passed, as in the development.log

Processing ItemsController#update (for ::1 at 2009-09-25 06:34:23) [PUT] Parameters: {"commit"=>"Update", ... "id"=>"228", "item"=> {..."category_id"=>["2"], ...}}

This looks a bit odd, why is it passing the id as a single element array I wonder? See below

[4;35;1mPage Load (1.1ms) [0m [0mSELECT * FROM "pages" ORDER BY position [0m [4;36;1mUser Load (0.6ms) [0m [0;1mSELECT * FROM "users" WHERE ("users"."id" = 1) LIMIT 1 [0m [4;35;1mItem Load (0.7ms) [0m [0mSELECT * FROM "items" WHERE ("items"."id" = 228) [0m Redirected to http://localhost:3000/items/228 Completed in 102ms (DB: 2) | 302 Found [http://localhost/items/228\]

and for different updates, the number in category_id is changing. In my controller, I have the provided boilerplate for update:

def update @item = Item.find( params[ :id ] )

respond_to do |format| if @item.update_attributes(params[:item]) ...

Am I missing something in the controller? Does a collection need to be handled separately?

Many TIA, Craig

> Hi Gurus, I'm trying to tackle a drop down list. I have category and > item dbs, and they're wired up with category has_many :items and item > belongs_to :category, and an item has a category_id. I have this code > in my new/edit.html.erb for item:

> <%= f.collection_select :category_id, > Category.find_main, :id, :header, {}, :multiple => false %>

I don't see anything wrong with this.

> And a pretty drop down list comes up, but no matter what I do, I can't > save an item with a different category--it always stubbornly records > the same one (or doesn't change it at all). The source html code > generated is:

> <select id="item_category_id" name="item[category_id]"><option

There is the problemI think, the extra set of for item[category_id]. Are you sure you have item belongs_to :category? It is as if it thinks there should be an array of id values.

Colin

Thanks again, Colin--in item.rb:

belongs_to :category

And in category.rb:

has_many :items

Item has a field category_id which I intended to populate with the links from an item to its category. The field header in the category db is where the name of the category is.

Am I setting it up wrong then to have:

<%= f.collection_select :category_id, Category.all, :id, :header, {}, :multiple => false %>

in the form? It does show up as a drop down box with the names populated in it.

Again, thanks super for helping me figure this out, Craig

If I replace

f.collection_select :category_id, Category.all, :id, :header, {}, :multiple => false

with just

f.collection_select :category_id, Category.all, :id, :header

it works!

Is this a bug, or is it me being an idiot?

TIA, Craig

That should be fine as far as I can see, though I don't understand the extra in the html you showed. One question, you said that it is not saving the new category id value, are you sure that it is not saving it, or is it possibly just not displaying it when you come round next time. Have a look in the db to see.

Another question, in an earlier post you showed the record being saved by update_attributes, what are you doing if that fails? In other words is the save succeeding?

I am getting to the point where I don't know what is happening I am afraid.

Colin

The weird thing is that it is working now with f.collection_select :category_id, Category.all, :id, :header instead of f.collection_select :category_id, Category.all, :id, :header, {}, :multiple => false

so :multiple => false seems to be the problem. But why? Is this a bug?

Again, many thanks, Craig

The weird thing is that it is working now with f.collection_select :category_id, Category.all, :id, :header instead of f.collection_select :category_id, Category.all, :id, :header, {}, :multiple => false

so :multiple => false seems to be the problem. But why? Is this a bug?

It does seem odd. If you had said :multiple => true then I would expect to see an array of ids in params, which is what you have. It is as if the :multiple has triggered the use of an array even though you have specified it as false. In fact of course using false is I believe redundant as this is the default. I could not find anything in the docs that specifies what should happen with a false setting (as opposed to no setting). Perhaps it is intended like this, nil means there will always be a single selection, true or false means it should be passed as an array (which is what caused your code not to work) and it either will actually allow multiple selections or not. There would be some logic in this for a user who wanted at run time to decide on whether multiple selections were allowed so he could use :multiple => current_option_setting and the code picking up the params would always expect an array whatever the setting of current_option_setting.

Colin