8 Insanely Useful ActiveAdmin Customizations
Mike Ackerman, Former Senior Developer
Article Category:
Posted on
Here at Viget, we've successfully used ActiveAdmin on a number of custom CMS projects. ActiveAdmin is a great help in providing a sensible set of features out-of-the-box, while still allowing heavy customization for great justice. It also has a very opinionated way of doing things, which can make customization a bit tricky (eg. layouts via Arbre, Custom Pages, etc.)
After working with ActiveAdmin for a couple of years, here are 8 customizations that I find myself using often:
1. Adding a custom behavior to ActiveAdmin::BaseController:
Often times, you'll want to add a before_filter
to something like your typical ApplicationController
, but scoped to the ActiveAdmin engine. In this case, you can add custom behavior by following this pattern:
# config/initializers/active_admin_extensions.rb:
ActiveAdmin::BaseController.send(:include, ActiveAdmin::SiteRestriction)
# lib/active_admin/site_restriction.rb:
module ActiveAdmin
module SiteRestriction
extend ActiveSupport::Concern
included do
before_filter :restrict_to_own_site
end
private
def restrict_to_own_site
unless current_site == current_admin_user.site
render_404
end
end
end
end
2. Conditionally add a navigation menu item:
When you have multiple admin types, you may want to only show certain menu items to a specific type of admin user. You can conditionally show menu items:
# app/admin/resource.rb:
ActiveAdmin.register Resource do
menu :parent => "Super Admin Only", :if => proc { current_admin_user.super_admin? }
end
3. To display an already uploaded image on the form:
ActiveAdmin uses Formtastic behind the scenes for forms. Persisting uploads between invalid form submissions can be accomplished via f.input :image_cache, :as => :hidden
. However you may want to display the already uploaded image upon visiting the form for editing an existing item. You could use set one using a hint (f.input :image, :hint => (f.template.image_tag(f.object.image.url) if f.object.image?)
), but this won't allow you to set any text as a hint. Instead, you could add some custom behavior to the Formtastic FileInput:
# app/admin/inputs/file_input.rb
class FileInput < Formtastic::Inputs::FileInput
def to_html
input_wrapping do
label_html <<
builder.file_field(method, input_html_options) <<
image_preview_content
end
end
private
def image_preview_content
image_preview? ? image_preview_html : ""
end
def image_preview?
options[:image_preview] && @object.send(method).present?
end
def image_preview_html
template.image_tag(@object.send(method).url, :class => "image-preview")
end
end
# app/admin/my_class.rb
ActiveAdmin.register MyClass do
form do |f|
f.input :logo_image, :image_preview => true
end
end
4. Scoping queries:
ActiveAdmin uses Inherited Resources behind the scenes. Inherited Resources uses the concept of resource
and collection
. ActiveAdmin uses a controller method called scoped_collection
which we can override to add our own scope.
In your ActiveAdmin resource definition file:
# app/admin/my_class.rb
ActiveAdmin.register MyClass do
controller do
def scoped_collection
Post.for_site(current_site)
end
end
end
Similarly, you can override the resource
method to customize how the singular resource
is found.
5. Customizing the method by which a resource is found by the URL:
Often times we add a "slug" to a resource for prettier URLs. You can use your friendly URL parameters in the CMS as well:
# app/admin/page.rb
ActiveAdmin.register Page do
controller do
defaults :finder => :find_by_slug!
end
end
I found that when a user submits the form while changing the slug value and the form is invalid, the next form submission will attempt to POST to the invalid slug. To fix this, I updated my model's to_param
method from:
def to_param
slug
end
To:
def to_param
if invalid? && slug_changed?
# return original slug value
changes["slug"].first
else
slug
end
end
6. Inserting arbitrary content into the form:
It can be handy to insert some explaining text, or even images, to within the Formtastic form itself. You'll need to insert the content into the form buffer:
Text:
form do |f|
f.form_buffers.last << "<li>My Text</li>".html_safe
end
Image:
form do |f|
f.form_buffers.last << f.template.image_tag('http://doge.com/image.png', :height => 350)
end
7. Dynamic Site Title:
It's possible you have multiple user types or sites that are managed via a single CMS. In this case, you may want to update the title displayed in the Navigation Menu.
# config/initializers/active_admin.rb
config.site_title = proc { "#{current_site.name} CMS" }
8. Manually defining sort order of top level navigation menu items:
It's easy to define the priority (sort order) of menu items when they belong to a parent, however if you are trying to set the sort order of top level parent items, it's a bit trickier.
# config/initializers/active_admin.rb
config.namespace :admin do |admin|
admin.build_menu do |menu|
menu.add :label => "First Item", :priority => 1
menu.add :label => "Second Item", :priority => 2
menu.add :label => "Third Item", :priority => 3
end
end
What customizations have you found that you think are worth sharing? Please leave a note in the comments below!