I’ve always been fascinated by Rubik’s cubes, how impossibly hard it has been for me to solve one, until I finally looked up the solution. Unlike many problems, a Rubik’s cube won’t really give you headaches. But it shares this thing in common with many problems, that once you know the solution, they almost disappoint by how easy and unchallenging they become.

I spend my days in the Admins of companies in the making, and as a mostly Rails developer, some Rails frameworks used most of the time got my attention. Very often, the same, simple questions arise on perceived limitations, that have incredibly easy workarounds.

I want to give solutions with ActiveAdmin and ForestAdmin to 5 Admin customization challenges that give headaches to some developers.

1- 💡 Showing values from my DB isn’t enough. How do I show computed values in my tables?

Computed values are used for several different purposes. It can be as simple as humanizing DB attributes to make them User-friendly, or they can be more complex use-cases and use relationships/associations to display sums of records, contextual labels, rankings… And else. :)

ActiveAdmin

With ActiveAdmin, computed on the fly values are called ‘status tags’ and are shown as read-only values. You can simply declare them when you register your resource:

status_tag 'In Progress'
# => <span class='status_tag in_progress'>In Progress</span>

status_tag 'active', class: 'important', id: 'status_123', label: 'on'

ForestAdmin

In Forest, “Smart Fields” do the same but can also be read-write instead of read-only. What’s more, Smart Fields can appear in both Index and Show views:

class Forest::User
  include ForestLiana::Collection 

  collection :users 

  field :fullname, type: 'String' do
    "#{object.firstname} #{object.lastname}"
  end 
end

2- 👩‍👦‍👦 How do I make forms for “has_many” associations work?

Has_many / belongs_to associations can be tricky to handle in ActiveAdmin. Let’s take the example of a class Multinational has_many Offices, and you would like to manually create new Offices belonging to a Multinationalfrom its details view.

ActiveAdmin

“Nested forms” do the trick. Add one to the view when registering the parent model:

ActiveAdmin.register Multinational do

  permit_params :name, :employees_number

  form do |f|
    
    ### Declare here the model's own form fields:
    f.inputs "Details" do
      f.input :name, label: "Company Name"
      f.input :employees_number, label: "Number of Employees"
    end
    
    ### Declare here the form for the child model, using the "has_many" method:
    f.inputs "Offices" do
      f.has_many :offices, heading: false do |o|
        o.input :location, label: "City Name"
        o.input :opened_at, :as => :datetime_picker 
     end
    end
    f.actions
  end
  
  # ...
end

ForestAdmin

With Forest you can use a Smart Action to do this, which adds flexibility as you can add a layer of logic which you will have to write in the controller. All the other fields can be hidden or shown by using the GUI layout editor in Edit Layout mode.

class Forest::Multinational   
  include  ForestLiana::Collection    
  collection :offices   

  action 'Create', fields: [    
    { field: 'location', type: 'String', isRequired: true},
    { field: 'opened_at', type: 'Date'}
  ] 
end

3- ⛔️ My Admin users keep touching/editing data that they shouldn’t touch. How can I keep them away?

Seeing critical data being lost because of a misuse of the Admin interface is upsetting.

ActiveAdmin

To protect your resources, add a call to actions to the ActiveAdmin resource that needs to be protected, and remove editing and/or deletion actions:

ActiveAdmin.register Office do
  actions :all, :except => [:destroy]
  # ...
end

What if you want to make your data read-only? In this case, you just need to explicitly declare only the actions you want to allow:

ActiveAdmin.register Office do
  actions :index, :show
  # ...
end

The main downside being that this disables the option for all users, but developers can of course keep accessing data through the good old console.

ForestAdmin

Forest handles this without code, directly from the UI. Hide or show the fields through the Layout Editor and use the team based permissions to manage access. In the “Settings” tab select “Teams” to create a group of users, and give the appropriate rights in the “Users” tab.

4- ⚙️ Help, my Admin is ugly / I don’t have enough UI features — Customizing the admin template.

ActiveAdmin

Customize the ActiveAdmin layout is made annoyingly hard as it is not actually defined as a layout file, but is generated programatically. Placing a custom layout in the layout directory will therefore not actually override the default layout.

A solution on StackOverflow however gives a workaround:

You can, however, monkey-patch or duck-punch the active admin layout methods inside your application.
The following will add an ie-specific stylesheet to the header:
module ActiveAdmin
  module Views
    module Pages
      class Base < Arbre::HTML::Document

        alias_method :original_build_active_admin_head, :build_active_admin_head unless method_defined?(:original_build_active_admin_head)

        def build_active_admin_head
          within @head do
            meta :"http-equiv" => "Content-type", :content => "text/html; charset=utf-8"
            insert_tag Arbre::HTML::Title, [title, active_admin_application.site_title].join(" | ")
            active_admin_application.stylesheets.each do |path|
              link :href => stylesheet_path(path), :media => "screen", :rel => "stylesheet", :type => "text/css"
            end
            active_admin_application.javascripts.each do |path|
              script :src => javascript_path(path), :type => "text/javascript"
            end
            text_node csrf_meta_tag
            text_node "<!--[if lt IE 7]>
            <link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\"admin_ie7.css\ />
            <![endif] -->".html_safe
          end
        end

      end
    end
  end
end

ForestAdmin

Forest allows to plug standard EmberJS components in place of its standard views (Called “Smart Views”). In Edit Layout mode, select a view you want to customize and click on the ⚙️ icon. Select the “Smart View” tab, and insert your own code (or choose code from the library of already available components).

The “Map” Smart View available in the Forest library

5- ♻️ How do I make my forms dynamically change depending on what is needed by the Admins?

In Rails, you can implement dynamic changes in your views by using embedded ruby, or rendering different views depending on the context.

ActiveAdmin

With ActiveAdmin, you can’t directly edit views, but you can make the changes programmatically in the ‘register’. The example below hides the password fields in the case the User already exists:

ActiveAdmin.register User do
  permit_params :first_name, :last_name, :email, :password, :password_confirmation
form do |f|
    f.inputs "User Details" do
        f.input :first_name
        f.input :last_name
        f.input :email
        if !f.object.new_record?
            f.input :password
            f.input :password_confirmation
        end
    end
    f.button :Submit
  end
end

ForestAdmin

Instead, Forest relies on its powerful Layout Editor to hide or show fields. In the UI, click on the “Edit Layout” button and uncheck the fields you don’t want displayed.

About ActiveAdmin and ForestAdmin

ActiveAdmin creates a CRUD interface for each resource thanks to a programmatical approach of hybrid separate files where both the logic and the views are declared.

ForestAdmin (Litterally For-REST) relies on its Liana Gem to build a secure API which is queried by the front-end from the browser. This allows to separate the logic from the UI.

→ 👋🏻 Thanks for reading. If you liked it, please ‘clap’ several times or share it so that more people can see it, and I keep writing on similar topics.

More about me here. You can also check out some of my other top articles: