I have observed that there is lot of confusions regarding
select box or collection helpers in Rails. Rails API documentation is not very
clear about which helper to use in which situation. In this blog, I have tried
to simplify the select box helper APIs by giving examples and various
scenarios. Majorily, there are two helpers which are helpful in creating a
select boxes in Rails select & collection_select. Though other helpers in the documentation are still useful but these are adequate to achieve anything.
The syntax for the select is
select(object,
method, choices, options = {}, html_options = {})
Let us start with the very basic select box:-
<%=select “post”, “person_id”, [“Person1”, “Person2”, “Person3”]%>
Output:
<select id="post_person_id"
name="post[person_id]">
<option
value="Person1">Person1</option>
<option
value="Person2">Person2</option>
<option
value="Person3">Person3</option>
</select>
Options for this Helper
<%=select “post”, “person_id”, [“Person1”, “Person2”, “Person3”],
{:include_blank => true}%>
Output:
<select id="post_person_id"
name="post[person_id]">
<option value=" "> </option>
…
</select>
Output:
<select id="post_person_id"
name="post[person_id]">
<option value=" ">Please select </option>
…
</select>
<%=select “post”, “person_id”, [“Person1”, “Person2”, “Person3”],
{:include_blank => “Please select”,
:disabled => [“Person1”, “Person2”]}%>
<%=select “post”, “person_id”, [“Person1”, “Person2”, “Person3”], {:include_blank => “Please select”, :selected => “Person1”}%>
Output:
<select id="post_person_id"
name="post[person_id]">
<option value="Person1" selected=”selected”>Person1</option>
<option
value="Person2">Person2</option>
<option
value="Person3">Person3</option>
</select>
HTML Options in the helper
Add HTML attributes
<%=select “post”, “person_id”, [“Person1”, “Person2”, “Person3”],
{:include_blank => “Please select”, :selected
=> “Person1”}, {:class => “html_class” }%>
Output:
<select id="post_person_id"
name="post[person_id]" class=”html_class”>
<option value="Person1" selected=”selected”>Person1</option>
<option
value="Person2">Person2</option>
<option
value="Person3">Person3</option>
</select>
Other methods to specify Choices in the helper
<%=select “post”, “person_id”, {“1” => “Person1”, “2”
=> “Person2”, “3” => “Person3”}%>
Or
<%=select “post”, “person_id”, [ [“Person1“, “1”], [“Person2”, “2”],[“Person3”, “3”]]%>
In case you have collection of objects
<%=select “post”, “person_id”, Person.all.collect{ |p| [p.name, p.id]}%>
The collection_select helper is also very useful if you have
collection of objects. For the above select it can written like this. It has
a syntax like:-
collection_select(object,
method, collection, value_method, text_method, options = {}, html_options = {})
So,
<%=collection_select “post”, “person_id”, Person.all, :id, :name%>
Grouped Select Boxes
In case you want to have grouped collection/select box there are two helpers which can help you create it grouped_collection_select
and grouped_options_for_select
grouped_options _for_select
is used along with select to group related options together.
<%
grouped_options = {“North America” => [[“United States”, “US”],
“Canada”], “Europe” => [“Denmark”, “Germany”, “France”]}
%>
<%=select “post”, “person_id”,
grouped_options_for_select(grouped_options), {:include_blank => “Please
Select”%>
There are more options like :divider, :prompt which you can pass
on to the grouped_options_for_select, whose details can be found here http://api.rubyonrails.org
Output:
<select id="post_person_id"
name="post[person_id]">
<option value="">Please
Select</option>
<optgroup label="Europe"><option
value="Denmark">Denmark</option>
<option
value="Germany">Germany</option>
<option
value="France">France</option></optgroup>
<optgroup
label="North Americal"><option value="US">United
States</option>
<option
value="Canada">Canada</option></optgroup>
</select>
grouped_collection_select helper is bit tricky to use and
has syntax like this
grouped_collection_select(object, method, collection, group_method,
group_label_method, option_key_method, option_value_method, options = {},
html_options = {})
This is what rails documentation has to say
Returns <select>, <optgroup> and <option> tags
for the collection of existing return values of method for object‘s class. The value
returned from calling methodon the instance object will be selected.
If calling method returns nil, no selection is made
without including :prompt or :include_blank in
the options hash.
Parameters:
·
object - The instance of the class to be used for
the select tag
·
method - The attribute of object corresponding to
the select tag
·
collection - An array of objects representing the <optgroup> tags.
·
group_method - The name of a method which, when called
on a member of collection, returns an array of child objects representing
the <option> tags.
·
group_label_method - The name of a method which, when called
on a member of collection, returns a string to be used as the label attribute for its<optgroup> tag.
·
option_key_method - The name of a method which, when called
on a child object of a member of collection, returns a value to be used as the valueattribute for its <option> tag.
·
option_value_method - The name of a method which, when called
on a child object of a member of collection, returns a value to be used as the contents of
its <option> tag.
Example object structure
for use with this method:
class Continent < ActiveRecord::Base
has_many :countries
# attribs: id, name
end
class Country < ActiveRecord::Base
belongs_to :continent
# attribs: id, name, continent_id
end
class City < ActiveRecord::Base
belongs_to :country
# attribs: id, name, country_id
end
Sample usage:
grouped_collection_select(:city, :country_id, @continents, :countries, :name, :id, :name)
Possible output:
<select name="city[country_id]">
<optgroup label="Africa">
<option value="1">South Africa</option>
<option value="3">Somalia</option>
</optgroup>
<optgroup label="Europe">
<option value="7" selected="selected">Denmark</option>
<option value="2">Ireland</option>
</optgroup>
</select>
Here, I have presented the form helpers which are not bonded
to any model. For forms which are bound to models use them as
<%=form_for @person%>
<%=f.select :person_id ….%>
<%=f.collection_select :person_id ….%>
<%end%>
That is all from my side. Here I have tried to cover every
possible scenario to create select boxes using rails helpers. Hope this will
help rails developer find the best suited helper for them.
In case you have any
questions/suggestions, you can connect to me at developer.vineet@gmail.com