13

I have a model MyModel with a serialized attribute a, describing an array of symbols.

This code works :

<% form_for @my_model do |f| %>
  <%= f.select :a, MyModel::AS, :multiple => true) %>
<% end %>

The parameters are correct :

{ :my_model => { :a => [:a_value1, :a_value2] } }

I want to transform this multiple select into a set of checkboxes, like this :

<% form_for @my_model do |f| %>
  <% MyModel::AS.each do |a_value|
    <%= f.check_box(:a_value) %>
  <% end %>
<% end %>

It works too, but the parameters are not the same at all :

{ :my_model => { :a_value1 => 1, :a_value2 => 1 } }

I think of 2 solutions to return to the first solution...

  • Transform my check_box into check_box_tag, replace multiple select, and add some javascript to 'check' select values when user clic on check_box_tags. Then, the parameter will be the same directly in the controller.
  • Add a litte code into the controller for 'adapting' my params.

What solution is the less ugly ? Or is there any other one ?

4 Answers 4

35

I found a solution, using 'multiple' option that I didn't know.

<% MyModel::AS.each do |a_value| %>
  <%= f.check_box(:a, { :multiple => true }, a_value) %>
<% end %>

Result parameters are a little weird, but it should work.

{"my_model" => { "a" => ["0", "a_value1", "0", "a_value2", "0"] }

Edit from @Viren : passing nil at the end of the function like

  <%= f.check_box(:a, { :multiple => true }, a_value, nil) %>

works perfectly.

Sign up to request clarification or add additional context in comments.

3 Comments

Pass nil at the end end and it would work as expected check this
Please edit your answer if you want, there is also an typo there. After <% MyModel::AS.each do |a_value| need %>. Just saying
My personal take on this: this would be an excellent way of defining roles that a user may have. That way, role definitions are hard-coded and you don't need any extra joins or queries to grab other data from the database because it's all there in your serialized field. Awesome!
8

There is another solution worth mentioning that makes it very easy to insert records into the database if you have a has_and_belongs_to_many or has_many through relationship by using the collection_check_boxes form helper. See documentation here.

<%= f.collection_check_boxes :mymodel_ids, MyModel::AS, :id, :name do |m| %>
  <%= m.check_box %> <%= m.label %>
<% end %>

Then, in the controller we would allow the mymodel_ids attribute:

params.require(:mymodel).permit(:name, mymodel_ids:[])

We can also set up a model validation to require that at least one of the checkboxes be checked:

validates :mymodel_ids, presence: true

An added benefit of this method is that if you later edit the mymodel record and uncheck one of the checkboxes, its record will be deleted from the many_to_many association table on save.

4 Comments

Is this anywhere in the guides? I couldn't find anything. Could you give me the link? Thanks!
@Metaphysiker, here's a link to documentation: edgeapi.rubyonrails.org/classes/ActionView/Helpers/….
Should the presence validation work correctly with this option? Or since collection_check_boxes includes an empty string, does the validation pass even though no checkbox has been checked?
@TravisSmith The presence validation definitely works, because Rails treats an empty strings as blank input and will not consider it present.
3

You can do it like this:

<% MyModel::AS.each do |a_value| %>
  <%= f.check_box("a[]", a_value) %>  
<% end %>

This will make params come to server as follows

{ :my_model => { :a => [:a_value1, :a_value2] } }

Comments

0

if you already have a select_tag

<%= select_tag "filters", options_from_collection_for_select(filter_values, "id", "name", selected_ids), multiple:true, class:"form-control" %>

and wants to replace it with check_box_tag, you will need to implement something like this:

<div class="checkbox-inline">
    <%= check_box_tag "filters[]", value.id, selected_ids.include?(value.id), { :multiple => true} %>
    <%= value.name %>
</div>

notice the ending brackets on the name which is needed to catch check box results in the same parameter.

When I implemented this, the parameters were of the same format between the select_tag and the check_box_tag

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.