Rails 4: Save Checkbox Results to Serialized Array
Asked Answered
C

1

10

I have a Campaign model with a channel column. This channel will store a serialized array of chosen results via checkboxes.

Here's the model..

app/models/campaign.rb

class Campaign < ActiveRecord::Base
    serialize :channels, Array
end

app/controllers/compaigns_controller.rb

class CampaignsController < ApplicationController
      def index
        @campaigns = Campaign.all.order("created_at DESC")
      end

      def new
        @campaign = Campaign.new
      end

      def create
        @campaign = Campaign.new(campaign_params)


        if @campaign.save

            zip = Uploadzip.find(params[:uploadzip_id])
            zip.campaign = @campaign
            zip.save

            flash[:success] = "Campaign Successfully Launched!"
            redirect_to @campaign
        else
            flash[:error] = "There was a problem launching your Campaign."
            redirect_to new_campaign_path
        end
      end

      def show
        @campaign = Campaign.includes(:program, :uploadzip, :channel, :plan, :uploadpdfs).find(params[:id])
      end

  private

      def campaign_params
        params.require(:campaign).permit(:name, :comment, :channel, :plan_id, :program_id, :campaign_id, uploadpdf_ids: [])
      end
end

The part of the form with checkboxes..

views/campaigns/_target.rb

<%= form_for @campaign, url: {action: "create"} do |f| %>

   ...

<label class="right-inline">
   <%= f.label :channel, "Distribution Channel", class: "right-label" %>
</label>

<ul class="channel-list">
    <% ["Folder", "Fax", "Email"].each do |channel| %>

    <li><%= check_box_tag :channel, channel %> <%= channel %>
        <% end %></li>
</ul>

...

<% end %>

I'm having problems saving these results inside the Campaign object.

Any help is highly appreciated.

Cluck answered 12/6, 2015 at 23:36 Comment(1)
first I think you each loop is wrong. In each loop you create a <li> and you have only one </li> out of the loop.Bydgoszcz
B
29

First of all, you mentioned that the column name is channel, but you have used its plural version in Campaign model. Since you are planning to save array of channels in this column, I would suggest you change the name of the column in the database to channels. All the code below assumes that you will change the database column to channels.

Since you are serializing the channels attribute to an Array and your form will send that parameter as an array to the controller, you will need to update your campaign_params method accordingly.

def campaign_params
  params.require(:campaign).permit(:name, :comment, :plan_id, :program_id, :campaign_id, uploadpdf_ids: [], channels: [])
end

Now, the relevant part of your @campaign form should look like this:

<ul class="channels-list">
  <% ["Folder", "Fax", "Email"].each do |channel| %>
    <li><%= check_box_tag "campaign[channels][]", channel, @campaign.channels.include?(channel), id: "campaign_channels_#{channel}" %> <%= channel %></li>
  <% end %>
</ul>

Explanation

First argument in check_box_tag is name attribute of the tag. Second is value attribute. Third is boolean value to tell whether the checkbox will be checked or not when rendered initially. This will be helpful in edit form to show current selections.

Note that I am providing id attribute explicitly. If we don't do that, all three checkboxes will have the same id (derived from their names), which would not be valid HTML because id should not be repeated.

Generated HTML should look like this:

<li><input type="checkbox" name="campaign[channels][]" id="campaign_channels_Folder" value="Folder" /> Folder</li>
<li><input type="checkbox" name="campaign[channels][]" id="campaign_channels_Fax" value="Fax" /> Fax</li>
<li><input type="checkbox" name="campaign[channels][]" id="campaign_channels_Email" value="Email" /> Email</li>

The controller will see channels param as an array of selected values.

This should work both for New and Edit forms.

Bagby answered 13/6, 2015 at 4:52 Comment(3)
This works! Thank you for the great response. Very thorough and easy to understand. Exactly what I needed.Cluck
Words, solution code, explanation of code. Also polite. Can SO please have more of you. 0/Nashville
Do you have a nice solution for the scenario where the value is always present, it's just a matter of "true" or "false"?Reify

© 2022 - 2024 — McMap. All rights reserved.