Why is the first element always blank in my Rails multi-select, using an embedded array? Why is the first element always blank in my Rails multi-select, using an embedded array? ruby-on-rails ruby-on-rails

Why is the first element always blank in my Rails multi-select, using an embedded array?


In Rails 4:

You will be able to pass :include_hidden option. https://github.com/rails/rails/pull/5414/files

As a quick fix for now: you can use right now in your model:

before_validation do |model|  model.subset_array.reject!(&:blank?) if model.subset_arrayend

This will just delete all blank values at model level.


The hidden field is what is causing the issue. But it is there for a good reason: when all values are deselected, you still receive a subset_array parameter. From the Rails docs (you may have to scroll to the right to see all of this):

  # 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 an +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_attributes(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.  #  # This way, the client either sends only the hidden field (representing  # the deselected multiple select box), or both fields. Since the HTML specification  # says key/value pairs have to be sent in the same order they appear in the  # form, and parameters extraction gets the last occurrence of any repeated  # key in the query string, that works for ordinary forms.

EDIT: The last paragraph suggests that you shouldn't be seeing the empty one in the case when something is selected, but I think it is wrong. The person who made this commit to Rails (see https://github.com/rails/rails/commit/faba406fa15251cdc9588364d23c687a14ed6885) is trying to do the same trick that Rails uses for checkboxes (as mentioned here: https://github.com/rails/rails/pull/1552), but I don't think it can work for a multiple select box because the parameters sent over form an array in this case and so no value is ignored.

So my feeling is that this is a bug.


In Rails 4+ set :include_hidden on select_tag to false

<%= form.grouped_collection_select :employee_id, Company.all, :employees, :name, :id, :name, { include_hidden: false }, { size: 6, multiple: true } %>