?assorted-color animal toy lot? by rawpixel on Unsplash
It?s nice to have options. Enter Ruby on Rails?s collection_select form helper. It generates an HTTP <select> tag and <option> tags that render a dropdown menu with multiple options
(Note: the helper method collection_check_boxes and collection_radio_buttons are similar, except they display each collection item with a checkbox or, you guessed it, a radio button.)
Generally?
This code:
collection_select(object, method, collection, value_method, text_method)
Creates HTML that looks something like:
<select name=”object[method]” id=”object_method”> <option value=”value_method”>text_method</option> <option value=”value_method”>text_method</option> …
Each item from the collection array is represented by an <option> tag. You can access the value_method of the submitted info through the params hash.
params[:object][:method] = [:value_method]
One argument at a time
Let?s walk through each of the five arguments. In the example below, from the Flatiron School curriculum, we?re building a new song form and want a dropdown menu that provides a selection of genres. Here?s the basic structure to get us started.
<%= form_for @song do |f| %> <%= collection_select(object, method, collection, value_method, text_method) %> <%= f.submit %><% end %>
1. object
The first argument, object, is the model object the form is all about, which in this case is @song. object and method together set the name and id attributes of the <select> tag, which determine how data is organized.
<%= form_for @song do |f| %> <%= collection_select :song, method, collection, value_method, text_method %> <%= f.submit %><% end %>
In this example, since we?re using collection_select with the form_for form builder, the object argument can be omitted since we already told the form which object we?re talking about.
<%= form_for @song do |f| %> <%= f.collection_select method, collection, value_method, text_method %> <%= f.submit %><% end %>
Which generates this HTML:
<select name=”song[method]” id=”song_method”> <option value=”value_method”>text_method</option> <option value=”value_method”>text_method</option>…
2. method
method , along with the first argument object , sets the name and id attributes of the <select> tag. To get the params property params[:song][:genre_id] my method argument :genre_id. which results in an id of song_genre_name. Note that method must be a property of object.
<%= form_for @song do |f| %> <%= f.collection_select :genre_id, collection, value_method, text_method %> <%= f.submit %><% end %>
And the corresponding HTML.
<select name=”song[genre_id]” id=”song_genre_id”> <option value=”value_method”>text_method</option> <option value=”value_method”>text_method</option>…
3. collection
collection, is an array of the options. In my case, it?s Genre.all, an array of Genre objects.
<%= form_for @song do |f| %> <%= f.collection_select :genre_name, Genre.all, value_method, text_method %> <%= f.submit %><% end %>
Each item in the array becomes an option tag.
<select name=”song[genre_id]” id=”song_genre_id”> <!– one option –> <option value=”value_method”>text_method</option> <!– another option –> <option value=”value_method”>text_method</option>…
4. value_method
value_method becomes the value attribute of each option tag. In this example, we make each option?s value equal to its id in the database.
<%= form_for @song do |f| %> <%= f.collection_select :genre_id, Genre.all, :id, text_method %> <%= f.submit %><% end %>
Resulting HTML:
<select name=”song[genre_id]” id=”song_genre_id”> <option value=”1″>text_method</option> <option value=”2″>text_method</option> <option value=”3″>text_method</option> <option value=”4″>text_method</option> <option value=”5″>text_method</option>…
After a user submits the new song form, the user?s selection is captured in its genre_id property.
The params hash might look something like:
params[:song] = {“title”=>”Stella”, “artist_name”=>”Mountain Man”, “genre_id”=>”14”}, “commit”=>”Create Song”, “controller”=>”songs”, “action”=>”create”}
Thus I can access my user?s selection through params[:song][:genre_id]. Pretty sweet.
params[:song][:genre_id] = “14”
5. text_method
text_method specifies which of the each item?s properties is displayed to the user in the list. In this case, we want to display each genre?s name property.
<%= form_for @song do |f| %> <%= f.collection_select :genre_id, Genre.all, :id, :name %> <%= f.submit %><% end %>
And the HTML:
<select name=”song[genre_id]” id=”song_genre_id”> <option value=”1″>Blues</option> <option value=”2″>Classic Rock</option> <option value=”3″>Country</option> <option value=”4″>Dance</option> <option value=”5″>Disco</option>…
To recap
- object and method form the name and id attributes of the resulting <select> tag. They define the structure for how data is stored.
- collection points to an array of choices.
- value_method becomes the value of the attribute. It contains the user?s selection.
- text_method is what?s displayed to the user in the dropdown
If you?re interested in digging a little deeper with collection_select, I recommend the Rails docs showing how collection_select fits together, starting with just the HTML tags.