Customizing ActiveAdmin Form
At Dexcode, we love ActiveAdmin. We've been using it in a couple of projects and we love its simplicity and elegant design. In this article, we want to share our experience with ActiveAdmin as a way for us to contribute back to the Ruby on Rails community.
When customizing ActiveAdmin, we found that new developers often stumble on the ActiveAdmin DSL and its lack of documentation. However, customizing ActiveAdmin form should not be hard because the ActiveAdmin form is implemented based on Formtastic
and in turn Formtastic
is implemented based on Rails ActionView FormBuilder
. So any Formtastic or rails helper code would work inside the ActiveAdmin form
block.
Examples
Let's work through some examples, the below examples assume that we want to customize the form for User
model.
Adding Hidden Field to ActiveAdmin Form
Let's say we have two types of users, admin users and normal users and we store this information in a role
column as a string in the users
table.
class User < ActiveRecord::Base
validates :role, format: { with: /\A(admin|normal)\z/ }
def admin?
role == 'admin'
end
def normal?
role == 'normal'
end
end
And we want to create a form for admin
users and normal
users separately. Thus, we will need to add a hidden input field to the ActiveAdmin form to force the user to be an admin
.
ActiveAdmin.register User, as: 'Admin' do
form do |f|
f.hidden_field :role, value: 'admin'
...
end
end
As you can see, the Rails form helper hidden_field
works in ActiveAdmin DSL, too.
Another way to do this is to use Formtastic
syntax which is very similar to simple_form
syntax.
ActiveAdmin.register User, as: 'Admin' do
form do |f|
f.input :role, as: :hidden
...
end
end
Nested Resource has_one Workaround
Another problem that we often have is dealing with nested resource with has_one
relationship. Let's say we have another model called Profile
that stores the user profile. In the ActiveAdmin form, we want the user form to have profile information shown as a nested resource of the user form. The problem is that ActiveAdmin form only supports has_many
attribute while the User and Profile information relationship is a has_one
relationship. Thus, first we need to initialize the profile information as part of the user information and second, we want to disable removing profile from the user. So, we come up with this solution:
ActiveAdmin.register User do
form do |f|
f.inputs "Profile", for: [:profile, f.object.profile || Profile.new] do |p|
p.input :first_name
p.input :last_name
end
end
end
Hopefully, the above information helps.