How to use collection_check_boxes – Ruby on Rails

This Post shows how to create a form with multiple check boxes using collection_check_boxes method.
Rails version: 4.2.5
DB version: SQLite3

Example here is softwares/new.html.erb view where you can choose one or more supported platforms.

STEP1: Create Software model and Platform model
Add an attribute :platform_ids to Software model. This attribute store platform ids in an array.  However, SQLite does not support array data type, so let db store platform_ids as a string and convert it back to array when you pull it out.

$ rails generate model Software name:string version:string platform_ids:text url:text

$ rails generate model Platform platform_name:string 

STEP2: Create controller & views for Software

$ rails generate controller softwares new edit 

STEP3: Edit softwares/new.html.erb

<%= form_for @software do |f| %>
  ...
  <%= f.label :supported_platform %><br/>
  <%= f.collection_check_boxes(:platform_ids, @platforms, :id, :platform_name) %>
  ...
  <%= f.submit "Save", class: 'btn btn-success' %>
<% end %>

After submission, an array of checked platform ids is stored in params[:software][:platform_ids].

STEP4: Edit controller (new & create)

class SoftwaresController < ApplicationController
  ...  
  def new
    @software = Software.new
    @platforms = Platform.all
  end

  def create
    @software = Software.new
    @software.assign_attributes(software_params)
    #convert the array of platform ids into a string
    @software.platform_ids = params[:software][:platform_ids].join(",")
    if @software.save
      flash[:notice] = "Software was saved."
      redirect_to action: :index
    else
      flash.now[:alert] = "There was an error saving the software. Please try again."
      render :new
    end
  end
  ...
  private 
  def software_params
    #don't include :platform_ids here because we need to convert it into a string
    params.require(:software).permit(:name, :versions, :url)
  end
end

STEP5: Edit softwares/edit.html.erb
Important:
Add { checked: @platform_ids_array.map(&:to_param) }  option as the last argument of collection_check_boxes. This pre-populates the collection check boxes just like other fields in edit form.

<%= form_for @software do |f| %>
  ...
  <%= f.label :supported_platform %><br/>
  <%= f.collection_check_boxes(:platform_ids, @platforms, :id, :platform_name, { checked: @platform_ids_array.map(&:to_param) }) %>
  ...
  <%= f.submit "Save", class: 'btn btn-success' %>
<% end %>

softwares/edit.html.erb view

STEP6: Edit controller (edit & update)

class SoftwaresController < ApplicationController
  ...
  def edit
    @software = Software.find(params[:id])
    #convert the string of platform ids into an array
    @platform_ids_array = @software.platform_ids.split(",")
    @platforms = Platform.all
  end

  def update
    @software = Software.find(params[:id])
    @software.assign_attributes(software_params)
    #convert the array of platform ids into a string
    @software.platform_ids = params[:software][:platform_ids].join(",")

    if @software.save
      flash[:notice] = "software was updated."
      redirect_to action: :index
    else
      flash.now[:alert] = "There was an error saving the software. Please try again."
      render :edit
    end
  end
  ...
  private
  def software_params
    #don't include :platform_ids here because we need to convert it into a string
    params.require(:software).permit(:name, :versions, :url)
  end
end

Done.

Leave a Reply

Your email address will not be published. Required fields are marked *