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 Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
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)