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?
2 Answers
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"))

- 1,848
- 22
- 20
-
Thank you, I like this approach! – roman-roman Aug 21 '14 at 15:29
-
1How would you add some customization to a particular subclass? Can we maybe pass block to `AnimalAdminCofig`'s constructor? – roman-roman Aug 21 '14 at 19:06
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

- 567
- 4
- 15