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