views:

285

answers:

2

Reading along with the agile book, it says this in a footnote:

... You simply pass the select helper the result of doing a find(:all) on your lookup table.

Okay ...

<%= f.select :source, Source.find(:all) %>

My source controller (and therefore table) looks like this:

create_table :sources do |t|
  t.string :source

  t.timestamps
end

But my select box is a mess, I get this type of data in all the values and displays:

#<Source:0x23a2bfc>

So I tried doing a Source.find(:all, :select => 'name,id') but that still gives me the whacky looking stuff.

What am I doing wrong?

+2  A: 
Source.find(:all)

will return an array of Source objects - this is not what you want. What you wants is an array of options. Something like:

select(:source, "source_id", Source.all.collect {|p| [ p.source, p.id ] })
askegg
Thanks, works perfectly. I knew there was something I had to do like this ... what's the difference between .collect and .map?
rpflo
There is no difference. `map` is an alias for `collect`.
Tate Johnson
+1  A: 

You need to pass a collection of options (or key-value options). The third parameter in select is actually passed to the options_for_select method. This is best illustrated with an example.

options_for_select(["a", "b"])

... becomes

<option>a</option><option>b</option>

Most of the time you'll be more interested in key-value pairs

options_for_select([["a", "1"], ["b", "2"]])

... becomes

<option value="1">a</option><option value="2">b</option>

As a short-hand, it's common to pass an entire collection of objects and map them to conform what options_for_select is expecting.

options_for_select(Model.all.map { |m| [m.attr1, m.attr2] })

...and to answer your question using the select method inside of a view

<%= f.select(:method, Model.all.map { |m| [m.attr1, m.attr2] }) %>
Tate Johnson
Thank you for the explanation. I'd have marked both as answers if I could since they do the same thing.
rpflo