Rails | ActiveAdmin |Custom checkboxes collection for array field

Sometimes you might want to store coherent information in single string field in database. For such fields you might want the Admin to have some mechanism to update.

In Rails you can have Array field like

# in migration file
# Array Types
t.string :open_days,       array: true, default: []
t.string :payment_options, array: true, default: []
t.text   :vehicle_vendors, array: true, default: []
t.text   :services_ids,    array: true, default: []

for such fields the form builder would look like

# I am using Formtastic syntax
f.input :payment_options, as: :check_boxes, collection: PaymentOption.all.map{|x| [x.name, x.id]}

# this will yield form like
<ol class="choices-group">
  <li class="choice"><label for="garage_payment_options_1"><input type="checkbox" name="garage[payment_options][]" id="garage_payment_options_1" value="1">Master Card</label></li>
  <li class="choice"><label for="garage_payment_options_2"><input type="checkbox" name="garage[payment_options][]" id="garage_payment_options_2" value="2">Visa</label></li>
  <li class="choice"><label for="garage_payment_options_3"><input type="checkbox" name="garage[payment_options][]" id="garage_payment_options_3" value="3">American Express</label></li>
  <li class="choice"><label for="garage_payment_options_4"><input type="checkbox" name="garage[payment_options][]" id="garage_payment_options_4" value="4">Diners Club</label></li>
  <li class="choice"><label for="garage_payment_options_5"><input type="checkbox" name="garage[payment_options][]" id="garage_payment_options_5" value="5">Debit Card</label></li>
  <li class="choice"><label for="garage_payment_options_6"><input type="checkbox" name="garage[payment_options][]" id="garage_payment_options_6" value="6">Fall</label></li>
  <li class="choice"><label for="garage_payment_options_7"><input type="checkbox" name="garage[payment_options][]" id="garage_payment_options_7" value="7">Financing and Installments</label></li>
  <li class="choice"><label for="garage_payment_options_8"><input type="checkbox" name="garage[payment_options][]" id="garage_payment_options_8" value="8">Paypal</label></li>
</ol>

When such data is submitted you can pry into it and find

pry(#<Admins::GaragesController>)> params[:garage][:payment_options]
=> ["", "2", "3", "4", "6"]

Now, the problem is, you have successfully gathered data from the admin; it will save the data if permitted properly but how would the form retain the already saved value?

ActiveAdmin.register Garage do
  permit_params :name, :some_column_name, {payment_options: []}
  # the empty array indicates that this attribute is gonna save an array data.

Now, to retain the selected value in the reloaded-form, try this

collected_data = PaymentOption.all.map{|x| [x.name, x.id, {checked: f.object.payment_options.include?(x.id.to_s)}]}
f.input :payment_options, as: :check_boxes, collection: collected_data

the checked: [boolean] determines whether to check the box while rendering.

Helpful Links

http://stackoverflow.com/a/39329678/3437900

http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters

Advertisements

4 thoughts on “Rails | ActiveAdmin |Custom checkboxes collection for array field

  1. Hi there, I have a couple problems, can you help? The first problem is that if i edit a record that doesn’t have any values saved yet to the db from this column, i receive this error undefined method `include?’ for nil:NilClass

    The second issue I have is that when I save the values and say I get [“”,”16″] stored in the db. When I edit that record it will show selected / checked for items 1, 6, and 16. How do I prevent that?

    Thanks

    Like

    • Here is what I have

      ActiveAdmin.register Job do

      menu parent: ‘Jobs’, label: “Job Listings”, priority: 0

      permit_params :userId, :employerName, :contactEmail, :employerPhone, :employerFax, :address1, :address2, :city, :state, :postalCode, :position, :description, :compensation, :payScale, :skillsRequired, {category: []}, :industry, :location, :jobStatus, :created_at, :updated_at

      index do
      selectable_column
      id_column
      column :position
      column :employerName
      column :contactEmail
      column :created_at
      actions
      end

      filter :employerName
      filter :contactEmail
      filter :userId
      filter :created_at

      form do |f|
      f.inputs “Job Details” do
      f.input :userId, label: ‘User’, :collection => User.all.map{ |user| [user.email, user.id] }
      f.input :employerName, label: ‘Employer Name’
      f.input :employerPhone, label: ‘Employer Phone’
      f.input :employerFax, label: ‘Employer Fax’
      f.input :contactEmail, label: ‘Job Contact Email’
      f.input :address1, label: ‘Address 1’
      f.input :address2, label: ‘Address 2’
      f.input :city, label: ‘City’
      f.input :state, label: ‘State’
      f.input :postalCode, label: ‘Postal Code’
      f.input :position, label: ‘Position’
      f.input :description, label: ‘Description’
      f.input :compensation, label: ‘Compensation’

      f.input :category, :as => :check_boxes, collection: JobClassification.all.map{|x| [x.classificationName, x.id, {:checked=> f.object.category.include?(x.id.to_s)}] }

      end
      f.actions
      end

      end

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s