Read more

Rails 4 introduced collection_check_boxes

Dominik Schöler
April 16, 2015Software engineer at makandra GmbH

Starting from Rails 4.0, you can use a special form options helper called #collection_check_boxes. It behaves similar to #collection_select Show archive.org snapshot , but instead of a single select field it renders a checkbox and a label for each item in the collection.

= form_for @post do |form|
  = form.collection_check_boxes :author_ids, Author.all, :id, :name_with_initial

How generated form params look like

Illustration online protection

Rails professionals since 2007

Our laser focus on a single technology has made us a leader in this space. Need help?

  • We build a solid first version of your product
  • We train your development team
  • We rescue your project in trouble
Read more Show archive.org snapshot

If you have authors with the IDs 1, 2 and 3, the check boxes above will be named like this:

<input type="checkbox" name="post[author_ids][]" value="1">
<input type="checkbox" name="post[author_ids][]" value="2">
<input type="checkbox" name="post[author_ids][]" value="3">
<input type="hidden" name="post[author_ids][]" value="">

Note the hidden input at the end. This is a trick that Rails uses so users can uncheck all the check boxes. If this hidden input wasn't there, the form param author_ids[] would be missing from the params entirely, and the list would not be set on your model.

In your Rails controller, this will create params like this:

{ 'post' => { 'author_ids' => ['1', '2', '3', ''] } }

Permitting array params in your controller

Note that you need some special syntax to whitelist an array-valued parameter in your controller.

This will not work:

params[:post].permit(:subject, :body, :author_ids)

In your server log you will see a line:

Unpermitted parameters: author_ids

You need to say this instead:

params[:post].permit(:subject, :body, :author_ids => [])

Also, you might need to remove the blank when processing the parameter. You can do so like this:

p = params...
p[:author_ids].reject!(&:blank?) # Remove Rails' blank collection item

Customizing the output

You can customize the output by passing a block. The block will be called with a special builder object that has a handful of special methods. See the complex example below.

form.collection_check_boxes :author_ids, Author.all, :id, :name_with_initial do |b|
   b.label { b.check_box }
   # or
   b.label(class: "my-#{ b.object.class.name.parameterize }", 'data-value': b.value) { b.check_box + b.text }
end

The return values of each call will be joined and returned. You may of course render HTML inside the block:

# _fields.html.haml

= form.collection_check_boxes :author_ids, Author.all, :id, :name_with_initial do |b|

  .my-checkbox-wrapper
    = b.label do
      = b.text
      = b.check_box

Radio buttons

There is also #collection_radio_buttons Show archive.org snapshot .

Posted by Dominik Schöler to makandra dev (2015-04-16 09:48)