5

I have a settings model with a column options, and set it to serialize with serialize :options. In my view, I have a multiple selection box, using select("settings", "options", ['option1','option2','option3'], {}, :multiple => true) which works fine so long as the user selects at least one option. However, if they don't select any options, no options are submitted and so the options aren't updated.

How do I allow the user to select zero options from a multiple selection box in rails?

Simon
  • 25,468
  • 44
  • 152
  • 266

4 Answers4

4

That has nothing to do with rails: html form won't send such parameter to server if nothing is chosen in 'select' element. But you should be able to fix it in controller. Something like this

if params[:settings] == nil
  params[:settings] = [];
end

Not sure if there's more elegant solution.

Nikita Rybak
  • 67,365
  • 22
  • 157
  • 181
  • 6
    `params[:settings] ||= []` – theIV Jul 29 '10 at 15:31
  • theIV's solution is perfect, especially for multi-select boxes with no blank option. – Matthew Clark Nov 03 '11 at 16:40
  • 1
    This strategy is can have unintended effects if you also use the same action for handling other requests. Rails assumes that if you are updating and not sending the attributes that it does not need to update excluded attributes. Forcing the attribute to be empty if not sent as a param can be a potentially dangerous assumption. I posted an alternate approach below using hidden input fields. – Sean McCleary Jan 25 '12 at 18:28
4

Add a hidden field after the select box, that posts an empty value to "settings[options]"

It's same trick that rails uses to make sure unchecked checkboxes get posted as false.

2

I do not like assuming a value is empty if the attribute is not posted. It breaks the way Rails expects to update attributes, and it can present problems if you are using your controller actions also for APIs as well as HTML. My preferred way of handling this is by adding a hidden input field before multiselects.

<input type="hidden" value="" name="parent_model[my_attribute_ids][]">

If you use JQuery you can automate the addition of these hidden input fields:

$('select[multiple="multiple"]').each(function(i){
    $(this).before('<input type="hidden" name="'+this.name+'" value="" />')
});

I realize this answer is not very timely, but I hope this will help someone with a similar question.

Sean McCleary
  • 3,690
  • 4
  • 33
  • 43
1

You could provide a "None" option.

Example from: http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html

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

Would become

<select name="post[person_id]" multiple="multiple">
  <option value="">None</option>
  <option value="1">David</option>
  <option value="2" selected="selected">Sam</option>
  <option value="3">Tobias</option>
</select>
maček
  • 76,434
  • 37
  • 167
  • 198
  • That makes for an odd interface - what does it mean if they select None and David? And it still does unexpected things if they don't select anything. – Simon Aug 13 '10 at 08:21
  • if they don't select anything then nothing happens - instead of clearing the association as it should. – Simon Sep 20 '10 at 09:47