Collection_select: What the heck?

Collection_select: What the heck?

Image for post?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.

24