method

select

rails latest stable - Class: ActionView::Helpers::FormOptionsHelper
select(object, method, choices = nil, options = {}, html_options = {}, &block)
public

Create a select tag and a series of contained option tags for the provided object and method. The option currently held by the object will be selected, provided that the object is available.

There are two possible formats for the choices parameter, corresponding to other helpers’ output:

Example with @post.person_id => 2:

select :post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true })

would become:

<select name="post[person_id]" id="post_person_id">
  <option value="" label=" "></option>
  <option value="1">David</option>
  <option value="2" selected="selected">Eileen</option>
  <option value="3">Rafael</option>
</select>

This can be used to provide a default set of options in the standard way: before rendering the create form, a new model instance is assigned the default options and bound to @model_name. Usually this model is not saved to the database. Instead, a second model object is created when the create request is received. This allows the user to submit a form page more than once with the expected results of creating multiple records. In addition, this allows a single partial to be used to generate form inputs for both edit and create forms.

By default, post.person_id is the selected option. Specify selected: value to use a different selection or selected: nil to leave all options unselected. Similarly, you can specify values to be disabled in the option tags by specifying the :disabled option. This can either be a single value or an array of values to be disabled.

A block can be passed to select to customize how the options tags will be rendered. This is useful when the options tag has complex attributes.

select(report, :campaign_ids) do
  available_campaigns.each do |c|
    tag.option(c.name, value: c.id, data: { tags: c.tags.to_json })
  end
end

Gotcha

The HTML specification says when multiple parameter passed to select and all options got deselected web browsers do not send any value to server. Unfortunately this introduces a gotcha: if a User model has many roles and have role_ids accessor, and in the form that edits roles of the user the user deselects all roles from role_ids multiple select box, no role_ids parameter is sent. So, any mass-assignment idiom like

@user.update(params[:user])

wouldn’t update roles.

To prevent this the helper generates an auxiliary hidden field before every multiple select. The hidden field has the same name as multiple select and blank value.

Note: The client either sends only the hidden field (representing the deselected multiple select box), or both fields. This means that the resulting array always contains a blank string.

In case if you don’t want the helper to generate this hidden field you can specify include_hidden: false option.

13Notes

Demo: select onchange invoke an ajax

alvin2ye · Jul 22, 200815 thanks

====

select("order", "customer_id", o.customer.collect {|c| [ c.label, c.id ] }, {:include_blank => true, :selected => o.customer_id }, :onchange => remote_function(:update => "message_id", :method => "put", :with => "'item=' + value",
:url => { :controller => :orders, :action => :set_customer_id, :id => order.id}))

Prompt vs. Select

rxcfc · Oct 24, 200813 thanks

According to the docs in form_options_helper.rb

:include_blank - set to true or a prompt string if the first option element of the select element is a blank. Useful if there is not a default value required for the select element.

:prompt - set to true or a prompt string. When the select element doesn't have a value yet, this prepends an option with a generic prompt -- "Please select" -- or the given prompt string.

The main difference is that if the select already has a value, then :prompt will not show whereas the :include_blank always will.

Add empty option and text is -select-

RobinWu · Jul 4, 200812 thanks

select :object, :method, options, :prompt => '-select-'

Refactoring excessive code for selects

Mange · Jan 8, 200910 thanks

@garg: It is not recommended to have excessive code in the views. You should refactor your code a bit. <%= f.select(:manufacturer_id, Manufacturer.find(:all).collect {|u| [u.name, u.id]}, :prompt => 'Select') %> could be changed to this: # in app/helpers/manufacturer_helper.rb def manufacturers_for_select Manufacturer.all.collect { |m| [m.name, m.id] } end

# in the view
<%= f.select(:manufacturer_id, manufacturers_for_select, :prompt => 'Select') %>

I would look into collection_select though: <%= f.collection_select(:manufacturer_id, Manufacturer.all, :id, :name, :prompt => 'Select') %> It's much more clean and you don't have to define a helper for it to be readable (altough it's still quite long).

If you have to do this often, you should define a FormBuilder extension, so you get methods like +f.manufacturer_select+: <%= f.manufacturer_select(:manufacturer_id, Manufacturer.all) %> IMO, most projects should have a custom form builder anyway, so the addition would be very small. This is my personal opinion, so you don't have to listen to it. :-)

selected

alvin2ye · Jul 22, 20086 thanks

====

select :languages, :language, ['en', 'de', 'fr'], {:selected=> 'en'}

":prompt" doesn't work

dvdplm · Jul 28, 20082 thanks

This does not work:

select :object, :method, options, :prompt => ’-select-’

This does work:

select :object, :method, {:include_blank => ’-select-’}

When using enumerables

mrbongiolo · Aug 9, 20102 thanks

When using enumerables and storing them as strings in the database don't forget to use .to_s or the select helper won't automatically select your choice when viewing your data after save.

Exemple:

dates = 1900..Date.today.year
f.select(:year, dates.collect {|d| [d.to_s,d.to_s]}, {:include_blank => "Select"}, {:class => "some_class"} )

style for select

mihserf · Nov 13, 20091 thank

====
<%= select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, {}, :style => "width:100px" %>

Different Options

bradly · Sep 22, 2008

The docs don't give any detail to what options are available, so I dug around and I think the only to options are :prompt and :include_blank

Using custom object via :object

avakhov · Aug 18, 2009

Sometimes you need use select not only with @object as by default. For example if you have helper method like :

def select_parent_for(page)
select(:page, :parent_id, Page.all.collect{|p| [p.name, p.id]} ) # <--- mistake!
end

In selected line you will use @page instead parameter of method page.

The options has parameter +:object+ (and all form helpers has such parameter)

Solution:

def select_parent_for(page)
select(:page, :parent_id, ..., :object => page)
end

@Mange

weexpectedTHIS · Oct 3, 2011

If you're actually looking to cut down on code why not use .map instead of the longer .collect?

Update for Rails 4

NikhilT · Mar 27, 2014

====In the example

select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, { include_blank: true })

It can be updated to

select("post", "person_id", Person.pluck(:name, :id), { include_blank: true })

not submitted even if non-multiple in certain cases.

rogerdpack · Mar 29, 2017

As a note, just for followers, even if a select is not "multiple" if it is "unselected" (ex: in javascript you can set its value like document.getElementById('select_id').value = 'a non option'; ). And if that form is submitted, the browser also seems to not send anything about it to the server. So it's for non-multiples as well, just this case is rare since typically the select will default to its "first value" and then users can only change it another known value, so typically you won't run into that. This isn't related to rails but thought I'd mention it.