It seems like, in current Rails, there’s not a very helpful helper around to give you select boxes which allow multiple items to be selected. So I present you with one:
def collection_select_multiple(object, method,
collection, value_method, text_method,
options = {}, html_options = {})
real_method = "#{method.to_s.singularize}_ids".to_sym
collection_select(
object, real_method,
collection, value_method, text_method,
options,
html_options.merge({
:multiple => true,
:name => "#{object}[#{real_method}][]"
})
)
end
And now it all works by magic — in my case the current categories that an article has are selected when the edit page comes up, and any changes are correctly saved back to the db. But it’s not nice enough. There’s still a lot of ugly code in the view. Let’s tidy things up by adding another helper:
def collection_select_multiple_categories(object, method,
options = {}, html_options = {})
collection_select_multiple(
object, method,
Category.find(:all), :id, :title,
options, html_options
)
end
Now the call in the view looks like:
<%= collection_select_multiple_categories :article, :categories %>
Ah, doesn’t that look much more like what we’re used to?
Oh, beautiful
I’m going to bookmark the post, the helper might be useful in a near future
Thanks
It’s a really well made piece of code !
Just a question: you use a Category.find(:all) in the code, by this way you need to create another helper if you’re using a collection that is different from Category.find(:all).
Maybe isn’t better to add another arg to “collection_select_multiple_categories” ?
Doing so you can specify time to time what is the collection you want to use.
Sandro: That’s effectively what the first helper has become. You can call it along the lines of:
in your view and it will do the right thing. I just like the idea of taking as much as possible out of the view…
When the name ends with “[]“, the html gets a warning from the tidy validator. Also, these names can’t be referenced in javascript as “[]” indicates array to js.
dagny: Yeah, but that’s the rails idiom for these things. As for referencing them, don’t you use the
idrather than thename? Rails does the right thing and, in my particular example, calls the idarticle_category_ids.FWIW, the W3C Validator doesn’t seem too fussed about the name having a ‘[]‘ in it.
Nice helper. However, I would tend to go for a list of checkboxes in this scenario, you can still use the “name[]” kind of field naming.
This doesn’t compile for me. I think
collection_select( object, real_method, collection, value_method, text_method, options, html_options.merge({
the above part should be as below
collection_select( object, method, collection, value_method, text_method, options, html_options.merge({
Also this doesn’t work on edit mode (doesn’t give preselected items hightlighted
Thanks Mathie, I am using your method for multi-selection box. It is working fine..
Hey cud u help me please.. I am a beginner for ruby on rails trying to develop a shopping cart cud u point me the rite tutorials which will help me understand things better Thanks..
Hi Graeme,
Thanks very much for this!
But, with this method I can’t unselect all categories in the form — I mean, if I chose one previously, then I can’t unchose it (without choosing another one).
Can you confirm this?
And, if this is a bug, how would one go about fixing it?
TIA
ok, got it — it’s an option f select[xxx] methods
thanks again f this great helper!
The code for the view works very well but due to the fact that the attribute name is pluralised in my case its interest_id_ids I can’t seem to save the records to the particular model.
Please help
sir,
i am having problems while using collection_select,i want to know how to use the selected value option in colletion select,heres my code :
<%= collection_select(:template_1, :templates_id, Template.find(:all,:joins=>”right join user_templates on user_templates.template_id = templates.id inner join users on users.id = user_templates.user_id”,:conditions => “users.id=’#{session[:id]}’” ),:template_id, :TemplateTitle,{ :prompt => “Select Template”},{:name=>’template’,:style => “color: green”}) %>
Excellent code. Thank you for sharing.
This is great! A Timesaver. Thanks!