Posted about 4 years ago. Visible to the public. Repeats. Linked content.

Rails 4 introduced collection_check_boxes

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

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

How generated form params look like

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

Copy
<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:

Copy
{ '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:

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

In your server log you will see a line:

Copy
Unpermitted parameters: author_ids

You need to say this instead:

Copy
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:

Copy
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.

Copy
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:

Copy
# _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.

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for old versions of Ruby on Rails (3.2 and 2.3).

Owner of this card:

Avatar
Dominik Schöler
Last edit:
5 months ago
by Dominik Schöler
Keywords:
strong, params, strong, parameters
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Dominik Schöler to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more