shiningthrough

Select helper methods in Ruby on Rails

01 May 2007

It can get quite confusing when it comes to using the different select helpers, select, select_tag and collection_select and in my opinion there is a lack of adequate documentation.
For my own use if nothing more, i have done my best to compare the different form helper methods available, and when and how to use them.

First we will look at the html for a basic selection box:

<select name="payment">
 <option value="1">VISA</option>
 <option value="2">MasterCard</option>
 <option value="3">Switch</option>
</select>

The selection box has some key parts, the name, which is required, and used by the browser when submitting the <select> choices to the server.

The option tags, each of which are made up from a "value" and "text" pair, the "value" to identify the select item in the server, and the "text" which will be displayed to the user.

There are three different select form helpers in ruby on rails, "Select", "select_tag" and "collection_select". We will have a closer look at each of them now.

select

select(object, method, choices, options = {}, html_options = {})
Defined in ActionView::Helpers::FormOptionsHelper

Use select when you require a basic drop-down selection box populated with data not sourced from a database.

In this example a hash is being used to populate the option tags.

<%= select( "payment", "id", { "Visa" => "1", "Mastercard" => "2"}) %>

Select can be used in conjunction with a model object as seen in this example, an instance variable is passed into choices, but is being converted into an array of arrays.

<%= select ("selected_payment", "id", @payments.map {|u| [u.name,u.id]}) %>

The controller may look something like this:

@payments = Payment.find(:all)
@selected_payment = @payments[2]

This will cause the third option_tag to be selected by default in the select box, but collection_select is preferable in this scenario.

select_tag

select_tag(name, option_tags = nil, options = {})
Defined in ActionView::Helpers::FormTagHelper

Use select_tag when you require a drop-down selection box populated with data not sourced from a database, and are happy to hard code the default selected option tag. Select_tag should also be used when you want to process your form as a GET, rather than a POST, see here for more details. Also note that select_tag does not have a html_options parameter

Simple use of the select_tag helper:

<%= select_tag "payment", "<option>VISA</option>" %>

In this example, we are using "options_for_select" which accepts any container and returns a string of option tags, but we have defined an array. Note how the optional second parameter specifies the selected item in the list.

<%= select_tag "payment", options_for_select([ "VISA", "MasterCard", "Switch" ], "MasterCard") %>

Another option is this

<%= select_tag "payment", options_for_select(%w{ VISA Mastercard Switch }) %>

where %w is the shortcut notation for an array of strings that are space separated.

You can also do multi-select boxes:

 select_tag 'payment[]', options_for_select(@payments), :multiple => true, :size => 3 %>

Note that the "name" in this case is an array, and @payments is a hash defined in the controller:

@payments = {'Visa' => 1, 'Mastercard' => 2, 'Switch' => 3}

We can access the selected payment methods in the controller, using the array:

params[:payment]

select_tag does not support the :prompt option, which may not seem like an issue as we have already shown above how you can select a default option tag. But what if you want your form to GET, not POST, your only option is then to use select_tag, even if your data source is a database.

<%= select_tag(:payment, "<option>-Select a payment method</option>" + options_from_collection_for_select(@payments, :name, :name)) %>

As select_tag takes a string, we can concatenate an additional string onto the beginning of the parameter, this allows us to add our default option_tag. We use options_from_collection_for_select which takes a value_method, and text_method (see collection_select for their definition) and an optional selected_value, and a collection, which can be defined in your controller like this:

@payments = Payment.find(:all, :order=>"name")

collection_select

collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
Defined in ActionView::Helpers::FormOptionsHelper

Use collection_select when you require a drop-down selection box, whose source is a model/object

In this example the payment methods are being added to the select box via a model object, notice how we use the option, :prompt to add an additional option tag to the select box, which will be selected by default. Note that if @object.method matches one of the option tags, this will be selected by default, and :prompt wont appear in the list.

<%= collection_select(:payment, :id, @payments, :id, :name, options ={:prompt => "-Select a payment"}, :class =>"payment") %>

The selected item can be accessed in the controller, by using:

selected_payment = params[payment][id]

A final Note to say that the parameters used in all the helpers may be strings or symbols, symbols may be a better choice in some situations, but thats another article.

Comments

RMax

Thanks for the write up, it certainly makes things clearer, i agree with you that there seems to be a lack of good offical documentation on this. Can you provide some more examples of using collection_select, and accessing this from the controller please.

shiningthrough

Thanks for the kind words RMax, i will provide some more examples of using collection_select in the near future.

Ash McConnell

Thanks, really cleared up a few things for me. I have been working with ruby for a few days now and i'm loving it! :)

Gaurav

Nice article

Nikhil Gupte

You mentioned that: -- Use select when you require a basic drop-down selection box populated with data not sourced from a database. -- This isn't correct since the _choices_ arg can take a value like: City.find(:all).collect {|c| [c.name, c.id]} This would fetch data from the db using the City model. In most cases the simple _select_ tag would work best. You could even do multiple select tags but using: {:multiple => true, :size => 5} as the html_options arg.

shiningthrough

Thanks for the feedback Nikhil, youll notice that i do give an example similar to the one you suggest, i just suggest that collection_select is preferable. I am curious to know why you think select_tag would work best in most cases?

SkyCFC

Hi! I'm skycfc, I ask the select_tag on #rubyonrails. I posted the article to: http://blog.pixnet.net/zusocfc/post/5574050 and http://zusocfc.blogspot.com/2007/06/rails.html In Traditional Chinese :) Thank you:)

weeznu

cool... very nice! :)

srijith

very nice 2 understand...

Czar

thats really a great article...but i have a problem...please help me. <%= select_tag "sort_type", options_for_select([ "new", "pending", "approved", "garbage" ], "new" ) %> This is what i have created using the example of visa and mastercard that you have given. Now, i have a submit button bellow the above code. When i select any of option selected and submit it, the control should remain only on the option SELECTED and not the "new" all the time. So in all i wanna put some dynamic variable in place of "new" so that everytime the page is submitted it retains the value of option selected and the not the "new" which is always going to be true in above case. thanks.

shiningthrough

Czar, if i understand you correctly you can achieve what you want by using my first example, the select helper. When the first selection has been made, store the value in either the database, a global variable, or class variable. Then @selected_payment can be set to any of these. Hope that answers your question.

Czar

I have done as you have said but it not working yet. I have saved the value of the option selected into an instance variable (ruby) named selected_variable as.....<%= select_tag "sort_type", options_for_select([ "new", "pending", "approved", "garbage" ], "<%@selected_variable%>" ) %>....but once i submit the page...i get this error........... ERROR : syntax error, unexpected $undefined, expecting ')' . _erbout.concat " "; _erbout.concat(( select_tag "sort_type", options_for_select([ "new", "pending", "approved", "garbage" ], "<%@selected_supplier).to_s); _erbout.concat "\" ) %>\n" ................................... i am trying everything from a week but not yet successful.... thanks a lot for previous answer

bleah12345

Hey, Good article man. One thing I've been trying to do that's driving me crazy(I'm a rails and ruby newbie) is get an onchange property on the select box to call a helper or controller method, passing to it the value of what was selected in the select box. Nothing I've tried worked. Have you ever done that? Any tips?

shiningthrough

bleah12345, this sort of think is covered very well in Railscasts, take a look at this: http://railscasts.com/episodes/43.

sumanth

I just stumbled across this article... and I am also looking for something similar that "czar " had mentioned in his comments. Let me put it this way--> in html select we have a provision where you can select a particular option using the keyword selected in the options, do we have similar thing in the rails form helper "select_tag" while the options are fetched dynamically from database tables.... Thanks in advance :)

shiningthrough

hi sumanth, why not just use collection_select?

Dave H

Thanks for the tips!

wildpalms

I struggled for a few days before I worked out how to get selected working so I'll post here for others: <%= select_tag(:selCuisine, "<option value="">Any cuisine</option>" + options_from_collection_for_select(@cuisines, :id, :cuisinename, params[:selCuisine].to_i) ) %> Note the ".to_i" <--that had me stumped for a while, then after thinking about it, even though the params[:selCuisine] seems like an integer, its not, hence the need to convert it to an integer for the selected option to be able to use it. Hope this helps folks...

Pavankumar Kulkarni

Hi, thanks a lot.. that really some air. I was really struggling with the documentation before I read your article. I think your article should be replaced by the present documentation!

Pavankumar Kulkarni

*cleared

Pablo

Thank you, this was helpful indeen.

mark

Thanks for the tutorial. I am having an issue trying to get the drop downs to work with rails 1.2.6 . I have implemented: <%= collection_select(:status, :id , @statuses, :id, :status) %> in _form.rhtml, the intention being to simply list the relevant status codes from the DB. In the controller I have implemented a find_all so that the @statuses variable is set. When I invoke the action I get: NoMethodError in Propagationrecords#new undefined method `status' for #<Status:0x4972c24 @attributes={"Status"=>"Grafted", "id"=>"4"}> Propagationrecords contains a status_id as a foreign key and I have mapped propagationrecords and status using: class Propagationrecord < ActiveRecord::Base belongs_to :status end class Status < ActiveRecord::Base has_many :propagationrecords end Anyone encountered this, or have I simply made a mistake in my approach?

shiningthrough

Hi Mark, are you still getting that error? i don't think its anything to do with your select helper, it looks to me like your not creating your @statuses collection correctly. Try iterating over your @statuses collection in your view first, with something like this: <pre> @statuses.each do |status| @status.code end </pre> Get this working before displaying them in a selection box.

Imran Lakhani

Its was really helpful Thanks buddy :)

Eric Colon

Thanks a lot! This article was extremely helpful and saved me hours of frustration.

Robert Rees

Thanks for this post. It's much clearer than the real documentation because you've contrasted the different methods and their different uses.

Don Kowalski

Thank you so much for posting the explanations about select, select_tag, and collection_select! It has made things much more clear. There is indeed a lack of "plain English" documentation which is odd for a language which boosts to be and is very readable.

Mac

Hey, Thanks for this. It would be really helpful if you showed how the select was used with a form, especially for the GET scenario as I am trying to do this and finding select with how to use the form in one place would be nice, Cheers

Prabhu

Can anyone explain me how to make an AJAX call in rails on selection of a list item? Thanks in advance

shiningthrough

@Mac - There is a select example with a "GET" form on one of my other posts, you can find it here:<a href ="http://shiningthrough.co.uk/GET+and+POST+in+Ruby+on+Rails"> Get and Post </a> @Prabhu - The way I do it is using RJS, to swap out the entire selection box with a new one that contains the updated data. If there is enough interest in this I could write a tutorial? let me know what you think.

Marc

Was wondering if anyone knows why the collection_select with multiple html_options adds '---' to the beginning of any entry for any selection made in the multiple select box.. basically this dropdown finds these 'indicator' strings in another table, and assigns it to another string in a different table. However, if I select anything from the drop down, it adds '---' to the beginning of each entry :( <%= collection_select(:datab, :indicator, Indicator.find(:all, :order => 'indicator'), :indicator, :indicator, {}, html_options = {:multiple => true, :size => 5}) %>

antony evans

I want to create a selection box with two choices, Hat lover and hat designer. Can anyone explain to me why this select tag isn't working: <%= select(:user_profile, :type, {"Hat lover", "Hat Designer"}) %> I get this error: TypeError in Community#edit_profile Showing app/views/community/edit_profile.rhtml where line #21 raised: wrong argument type String (expected Module) Extracted source (around line #21): 18: <%= text_field :user_profile, :location, :size => 30 %></p> 19: 20: <p><label for="name">Type</label><br/> 21: <%= select(:user_profile, :type, {"Hat lover", "Hat Designer"}) %></p> 22: 23: <p><label for="name">Owned hats</label><br/> 24: <%= text_field :user_profile, :owned_hats, :size => 10 %></p>

maige

>> The way I do it is using RJS, to swap out the entire selection box with a new one that contains the updated data. If there is enough interest in this I could write a tutorial? let me know what you think. I think that tutorial would be helpful to a lot of people, not to mention interesting. Please go ahead with the tutorial. I know I'm interested to read that one. ;)

aampal

Hi, Thanks, But how can I select value by default or onn some event? ... or what would be the selectedIndex

shiningthrough

@Antony - Looking at your code briefly, it appears that your 'choices' parameter is neither an array, or a hash. @Maige - I am currently working on one, watch this space! @aampal - Both 'Select' and 'collection_select' will allow you to set a dynamic default option in the selection box.

pepe

finally i got the "selected" for the collection_select helper, thanks a lot!! i only think that it would be clearer for newbies like me if you enforce the fact that the helper will look for the @payment variable and call it's id method to perform the comparison with the array @payments and generate the selected label.

Mike

What if you need to create a SELECT for a group of items that aren't directly related to the object? Which SELECT help do you choose? For instance, if I'm creating a user and I want a drop-box for "Number Of Times To Duplicate User", how do I create a drop-box that will pass values back?

Dodger

"The optional options argument takes various "options" some of which are listed below in the examples." No, no they are not, in fact, listed below in the select() examples or even mentioned again at all...

Bob Walsh

Finally! some decent documentation of select - thanks very much; perhaps you can contribute this back to rails doc project.

Tony

Thank you, this did the trick.

Srinivasan

Thanks a lot! This is a very nice writeup.

Mike

YOU ARE GOD! Thank you sooooo much!

Kristophr

I keep getting errors -or- I cannot get it to save to the database. The field I have in the database is called "bus_unit" (for business unit). I have this: <%= f.select :bus_unit, {"Transportation Management Services","Mid-Market (SLS)","Brokerage"} %> I've tried all the various examples that you have listed and I can either get the drop down box and not save, or just error. Any help would be greatly appreciated...

shiningthrough

Kristophr, i need more information, give me the code (that successfully creates a drop down) from your view, and your controller, along with any error messages.

Gavin

great help mate! thanks

Graham Pengelly

Thanks... I find myself referring to this post every few days due to an unexplained mental block regarding select helpers. Thought I should add a quick note of thanks...

Andy Lee

It took me quite some time surfing the net for the correct usage of select helper method, and you post is the day saver for me! thanks

moe

Great post. You are absolutely correct about the lack of documentation. I just wrote a blog on the select helper and came across your post. I added a link to it so hopefully more people can run across this great post. http://badpopcorn.com/blog/2008/09/02/rails-select-helper/

Jon Roberts

Thanks, I really benefited from this piece. I'm worried though that something so ordinary as setting up a select control should have become searched for by so many people. My productivity is not as high with Rails as it used to be ! In my case I am upgrading an app that worked fine 18 months ago but does not work with 2.x.

Suggestion

Very useful article. Thanks. I'd suggest submitting a documentation patch.

Ganesh K.

Thank you... got some new things..

primordial

top of google for good reason. a great article. Thanks, i always forget the various syntaxes.

Alex

Thanks for the info ;)

messymissy

Thanks for the info. But how if I want to do a comparison for SELECT values and Database values? How should I write for the database conditions (in PHP, called SQL query)? Thanks.

messymissy

problem solved.. thks.

boatshow

good job ,guy

ark

Thanks, it was very helpful for me.

Rafael Rosa Fu

Hi, Thanks for the info. You should consider adding your text to Rails Guides, the form tags section could use your text :) http://guides.rubyonrails.org/form_helpers.html Thanks a lot, Rafael. rafaelrosafu(at)gmail(dot)com

Senthil Raja

Hi Thanks for this useful stuffs. But what my need is not satisfied here... I want to have a multiple select box and values from model... and while editing i need to show existing data selected... Briefly my requirement is mingle multiple select with colection_select

shiningthrough

@Senthil - I am not sure I totally understand what you are trying to achieve, perhaps you are trying to create multiple selection boxes like this? <a href="http://www.excitingweddings.com" title="Exciting Weddings">Exciting Weddings</a>

Wild Invention

Thanks shiningthrough, that's really useful. I don't know why but rails select helpers get me every time. I don't suppose you know a way to respect the ordering do you without pulling from a database? I tend to hardcode when I need things in a particular order which isn't ideal.

pete

Hi, thanx for a great tutorial I'm trying to do a very basic select with some (numeric) values, stored as decimal. <% form_for(@ad) do |f| %> <%= f.select( :room, %w{ 1 1.5 2 2.5 3 3.5 }) %> it works great for saving, but when editing the form the saved value isn't selected. In "Agile Web Development with Rails" they have a very similar example, and they claim it should automatically select the saved value, in my case @ad.room I would be very grateful for any advice!

mattia

thank you so much!

Richard Smith

That just worked first time, thank you a million times! Richard

gazelle

heyi'm a newbie in rails i used the first code in my newuser view <select name="stat"> <option value="1">Married</option> <option value="2">Single</option> <option value="3">Divorced</option> </select> but how can i save the selected item to field "status" of my table "user" i have a form <% form_for(@user) do |f| %> thx in advance

Bendable

This is probably the best explanation I have found. Thanks a bunch!

kesava

@bleah12345 just use this.options[this.selectedIndex].value as the value to the onchange fucntion.

MickTaiwan

Thank you so much for this detailled explaination, that I google everytime I use a select. This time I decided to leave a comment. Thanks again.

René

Thank you so much. :)

uma mahesh varma

this post helps alot for ror developers. many developers are confused to use select options and what to use exactly. Thank you for your post....

Srikanth

Great Article ... used to Verify this article whenever i use select tag... cheers..

Danny

This article has the highest SEO out there for this subject, but hasn't cleared things up for me. Here's what solved my particular issue: if you have a table 'account' that has a column which saves the server_id that corresponds to the id from servers table: <%= select(:account, :server_id, Server.find(:all).collect{ |s| [s.name, s.id] }) %>

Sacha

For people looking for selected value on Danny's example (you want server with id = 3 to be default selection), and class name. <%= select :account, :server_id, Server.find(:all).collect{ |s| [s.name, s.id] }, {:selected => (3)}, {:class => "classname", :onchange => "alert('hello');" } %> Hope this help someone !

Jose Galvan

Thanks, I am novice on RoR and I find this a very helpful article, it really helped me...I had tried the examples on ruby on rails official site with no sucess, here you explain it with clarity.

norfolk_s3d

Thx OP, really cleared the syntaxis. Needs some explanation of options for newbies like me tho.

Adrien Lamothe

To answer Senthil Raja's question, to show an existing value in the model you use the :selected => @model.attribute option. In the following example, I'm using values from an AccountType table, to populate the list box: <% form_for @user, :url => user_path do |form| %> <%= form.label :login %> <%= form.text_field :login %> <%= form.label :email %> <%= form.text_field :email %> <%= form.label :account_type %> <%= select("user", "account_type", @account_types.collect {|t| [ t.account_type] }, :selected => @user.account_type) %> <%= form.submit "Update" %> <% end %>

shiningthrough

@Sacha - thanks for the input!

Ram

Please also tell us about f.select. Is it one of these too, as the no. of arguments look different

nursing schools

Great site. A lot of useful information here. I’m sending it to some friends!

hi

empisdini

shining movie quoates <a href=http://moviestrawberry.com/films/film_rembrandt/>rembrandt</a> vegas pain mistress domme dominatrix video film dvd phone movie http://moviestrawberry.com/films/film_the_safety_of_objects/ darkness the movie star trek the movie <a href=http://moviestrawberry.com/films/film_the_big_red_one/>the big red one</a> transformers movie sound off http://moviestrawberry.com/countries/?page=41 movie goggles movie and tv quotes <a href=http://moviestrawberry.com/films/film_red_planet/>red planet</a> movie oceon dumbo movie <a href=http://moviestrawberry.com/films/film_nostradamus/>nostradamus</a> washington dc movie premier http://moviestrawberry.com/films/film_anamorph/ the women meg ryan movie georgetown ma the reaving movie <a href=http://moviestrawberry.com/films/film_the_little_mermaid_ariel_s_beginning/>the little mermaid ariel s beginning</a> vegas cigarette torture video film dvd movie phone http://moviestrawberry.com/films/film_first_blood/ silver streal movie

Biju

Thanks for posting such a nice article. I have used this article many times in last 2 year. Sorry for posting comment so late.. Thanks again. Biju

glibiaengelix

<i>interesting, i will come back later on</i>

website

this is a great resource, but I was a little confused on the whole difference between select and select_tag. Both descriptions start off with use when data is not populated by the db, which causes my confusion.

Steave

Is there a video explaining the installation?

seema

how to specify id for collection select?

meiaowsh

this was helpful! thanks! :D

Rolando Murillo

Thanks for the good post and thanks @pete for the advice.

Pokerspiel

excellent points and the details are more specific than somewhere else, thanks. - Murk

Feedback Form

last few days our group held a similar discussion on this topic and you show something we haven't covered yet, thanks. - Laura

Jason

Suppose wanted to concatenate two values from the model as the text_method (for example, last and first name. What is the specific syntax for doing something like that? Method needed on the model?

circuit canada

Thanks for posting such a nice article. I have used this article many times in last 2 year. Sorry for posting comment so late.. Thanks again.

Professional

Repair your rss please, I reading blogs news via google chrome rss reader, thnks.

shiningthrough

@professional - It seems ok to me, in what way is it broken?

opthamologists

this post is very usefull thx!

Sara

I just wanted to say thank you for this! I can't believe that you wrote this in 2007 and there isn't more documentation around about this. I had to SEARCH to find you, but I'm so glad I did! This works for me and helps to clear up a lot of things for me.

ryananders

Hack again?!

Respiratory Therapist

Keep posting stuff like this i really like it

prasad

Thank You for clear explination all types of select tags

Jay

add :include_blank => "name to display" option to enable blank selection

Sid

Pretty useful stuff!

Rajib Ahmed

Thanks helped me a lot understanding the concept of these tags :)

mangochiman

Thanks for the tutorial. I was a blind person but now I can see. Thanks a lot.

Jump Rope Workout

This is a great post. Thank you : )

zands

thanks for the article!!! helped this newbie very much!!!

denmanjd

Thank you! This is the best explanation I have seen so far. Finally got something working now.

Press Release Distribution

I think there might be a little too much going on on the initial load of your blog. I see just the background for a couple seconds