We’ve been building a few web apps using Active Admin with great success. While Active Admin was primarily designed to create application back-ends, it is a great framework for building the customer facing part of Web Applications.

Customize Active Admin with Factories & Components

Active Admin layout can be customized using Factories. There are factories for the Title Bar, Navigation, Footer, etc. You can easily change the default footer with the following snippet of code:

ActiveAdmin.setup do |config|
  config.view_factory.footer = MyFooter
end
class MyFooter < ActiveAdmin::Component
  def build
    super(id: "footer")
    para "Copyright #{Date.today.year} Reverb Media Group"
  end
end

Checkout the ActiveAdmin::ViewFactory class in Active Admin for the full list of configurable views.

You can also create a custom component for the index view:

ActiveAdmin.register Post do
  index as: :list
end
class IndexAsList < ActiveAdmin::Components
  def build(page_presenter, collection)
    ul do
      collection.each do |obj|
        li auto_link(obj)
      end
    end
  end
end

Unfortunately, these features are not well documented, so you’ll have to dig into the code to find out more about customising Active Admin using components.

Split out your Fat Models into Services, Decorators and Presenters

There is a lot of discussion going on about Object Oriented Rails these days. Our approach is to put Business Logic into Services, Human Data into Decorators, Complex Data Manipulations into Presenters to move towards the single responsibility principle. Doing so makes our Models, Controllers and Helpers really slim.

Services: Business Logic

A Service implements the Business Logic of the application. It could be called from the UI, a REST API, a rake task… It can either be tested via Unit or Integration Tests. A Service is likely to rely on ActiveRecord models or other Services.

class SyncService
  def self.sync!(account)
    new(account).sync!
  end

  def initialize(account)
    @account = account
  end

  def sync!
    # fun stuff here
  end

  private

  def posts
    # more fun stuff here
  end
end

Decorators: One Model Data for Human

A Decorator adds methods for humans to a model.

class UserDecorator < Draper::Base
  decorates :user

  def full_name
    [user.first_name, user.last_name].compact.join ' '
  end
end

Presenters: Buncha’ Model’s Data for Human

Presenters gather data from multiple models and process it into an understandable data structure. We mostly use presenters for Reports or Activity Streams.

class ActivityReportPresenter
  def initialize(user)
    @user = user
  end

  def activity_items
    # ...
  end

  private

  # ...
end

Models: Data access, persistency and consistency

Our models are slim. They only take care of associations, validations, scopes and a few request & mutating methods.

Logic-less Views

Views either display a Model, a Decorator or a Presenter. There is almost no logic in them. Logic should live in the Decorator or Presenter.

Controller Actions

The CRUD actions are managed by Active Admin through InheritedResources. Custom actions are delegated to a Service.

member_action :sync do
  account = Account.find(params[:id])
  AccountSyncService.sync!(account)
  redirect_to account
end

 Rake Tasks and Scripts

Rake tasks and Scripts just load the environment and run a task defined in app/tasks. We usually put background tasks into rake tasks and daemon processes into scripts.

class SyncTask
  def self.run
    Account.find_each do |account|
      SyncService.sync!(account)
    end
  end
end

Active Admin?

Since we use Active Admin to build up the user facing UI, we move it from /app/admin to /app/ui.

Active Admin + SRP = Fast & fun development

Using Active Admin to build up the UI allows us to focus on the fun stuff while leaving Active Admin to deal with all the plumbing to tie things together.

Adding components, decorators, presenters, services and tasks into the mix makes your app much more modular and testable. Also, it makes you app folder looking like an enterprise app folder:

app/
 assets
 components
 controllers
 decorators
 helpers
 jobs
 mailers
 models
 presenters
 services
 tasks
 ui
 views

All right, I hope this gave you a good understanding of how we build modular web apps using Active Admin.

What about you? Do you use Activ eAdmin to build user facing UI? Are there any other design principles you follow such as DCI or Hexagonal Rails?