How do you handle serialized edit fields in an Active Admin resource?

sorens picture sorens · Nov 18, 2011 · Viewed 9.5k times · Source

I have a model, Domain, which has a text field, names.

> rails g model Domain names:text
  invoke  active_record
  create    db/migrate/20111117233221_create_domains.rb
  create    app/models/domain.rb
> rake db:migrate
==  CreateDomains: migrating ==================================================
-- create_table(:domains)
   -> 0.0015s
==  CreateDomains: migrated (0.0066s) =========================================

I set this field as serialized into an array in the model.

# app/models/domain.rb
class Domain < ActiveRecord::Base
  serialize :names, Array
end

Create the ActiveAdmin resource for this model

> rails g active_admin:resource Domain
    create  app/admin/domains.rb

then, in the app/admin/domains.rb, I setup the various blocks to handle the serialized field as such

# app/admin/domains.rb
ActiveAdmin.register Domain do

  index do
    id_column
    column :names do |domain|
      "#{domain.names.join( ", " ) unless domain.names.nil?}"
    end
    default_actions
  end

  show do |domain|
    attributes_table do
      row :names do
        "#{domain.names.join( ", " ) unless domain.names.nil?}"
      end
    end
  end

  form do |f|
    f.inputs "Domain" do
      f.input :names
    end
    f.buttons
  end

  # before we save, take the param[:domain][:name] parameter,
  # split and save it to our array
  before_save do |domain|
    domain.names = params[:domain][:names].split(",") unless params[:domain].nil? or params[:domain][:names].nil?
  end
end

Nearly everything works great -- my names are displayed as comma separated in the index and show views. When I update a record with my names field set to "a,b,c", the before_save works to turn that into an array that is then saved via the ActiveRecord serialize.

What I can not solve is how to make the edit form put in a comma-separated list into the text field. I tried using a partial and using formtastic syntax directly as well as trying to make it work via the active_admin DLS syntax. Does anyone know how to make this work?

Specifically, if I have the following array saved in my domain.names field:

# array of names saved in the domain active_record
domain.names = ["a", "b", "c"]

how to change:

      form do |f|
        f.inputs "Domain" do
          f.input :names
        end
        f.buttons
      end

so that when the edit form is loaded, in the text field instead of seeing abc, you see a,b,c.

Answer

sorens picture sorens · Nov 21, 2011

Here is a summary of how I handled this situation. I added an accessor to the model which can turn the Array into a string joined by a linefeed and split it back to an Array.

# app/models/domain.rb
class Domain < ActiveRecord::Base
  serialize       :names, Array
  attr_accessor   :names_raw

  def names_raw
    self.names.join("\n") unless self.names.nil?
  end

  def names_raw=(values)
    self.names = []
    self.names=values.split("\n")
  end
end

then, in my admin resource for domain, instead of using the :names field, I used the :names_raw field. setting this value would save the names Array with the new values.

# app/admin/domains.rb
form do |f|
  f.inputs "Domain" do
    f.input :names_raw, :as => :text
  end
  f.buttons
end