3

I'm using ActiveAdmin and I have a project with Single Table Inheritance. My question is simple: is possible to write only once the form of the common parts of my models or i am forced to rewrite it every time?

svarione
  • 61
  • 4

2 Answers2

4

You can use ruby's #to_proc and trick with conversion of a proc into a block.

Here's my solution leveraging it. It allows for normal code reloading, doesn't extend/monkey patch any existing modules and allows for customization of admin definitions.

In this example Animal is base STI class, Dog and Cat are inheriting from it.

Put the following code into app/admin/animal.rb:

class AnimalAdminConfig
  attr_reader :opts

  def initialize(opts = {})
    @opts = opts
  end

  def to_proc
    this = self

    proc do
      scope :active

      index do
        column this.opts[:name_label], :name
        column ....
      end
    end
  end
end

Put the following code into app/admin/cat.rb:

ActiveAdmin.register(Cat, &AnimalAdminConfig.new(name_label: "Kitten's name"))

Put the following code into app/admin/dog.rb:

ActiveAdmin.register(Dog, &AnimalAdminConfig.new(name_label: "Puppy's name"))
ku1ik
  • 1,848
  • 22
  • 20
2

I was having the same issue as you, and here is the solution that I came up with:

I had about 4 models that all inherit from Venue and I was re-writing all the params and logic for each one.

in config/initializers/active_admin_shared_venue_resources.rb

module ActiveAdmin
  class DSL

    def shared_venue_methods_and_traits(options={})

      #all your shared logic here

    end
  end
end

and then in admin/your_model.rb you just need to include whatever you called your method:

ActiveAdmin.register InheritedModel do
  menu priority: 1

  shared_venue_methods_and_traits
end

That will inject all the code from your initializer into the model.

THE CATCH: You will have to restart your server whenever you change the config file

Update:

For the forms I did the following:

Create a partial that has all the fields in views/admin/shared/_shared_form.html.erb

and then in views/admin/inherited_models/_your_form.html.erb you can put the following:

<%= semantic_form_for [:admin, @inherited_model], html: {multipart: true} do |f| %>
  <%= render '/admin/shared/shared_form', f: f, venue: @inherited_model %>
<% end %>

The venue variable isn't required. But will give you a way to call the @inherited_model variable in your form if you need to

RustComet
  • 567
  • 4
  • 15