Activeadmin Docs
Activeadmin Docs
More accurately, it’s a Rails Engine that can be injected into your existing Ruby on Rails application.
Otherwise, with no arguments we will create an AdminUser class to use with Devise:
rails g active_admin:install
Now, migrate and seed your database before starting the server:
rake db:migrate
rake db:seed
rails server
User: admin@example.com
Password: password
This creates a file at app/admin/my_model.rb to set up the UI; refresh your browser to see it.
Upgrading
When upgrading to a new version, it’s a good idea to check the CHANGELOG.
1 / 39
To update the JS & CSS assets:
rails generate active_admin:assets
You should also sync these files with their counterparts in the AA source code:
app/admin/dashboard.rb ~>
config/initializers/active_admin.rb ~>
Gem compatibility
will_paginate
If you use will_paginate in your app, you need to configure an initializer for Kaminari to avoid conflicts.
# config/initializers/kaminari.rb
Kaminari.configure do |config|
config.page_method_name = :per_page_kaminari
end
If you are also using Draper, you may want to make sure per_page_kaminari is delegated correctly:
Draper::CollectionDecorator.send :delegate, :per_page_kaminari
simple_form
If you’re getting the error wrong number of arguments (6 for 4..5) , read #2703.
2 / 39
General Configuration
You can configure Active Admin settings in config/initializers/active_admin.rb. Here are a few
common configurations:
Authentication
Active Admin requires two settings to authenticate and use the current user within your application.
Internationalization (I18n)
To translate Active Admin to a new language or customize an existing translation, you can copy
config/locales/en.yml to your application’s config/locales folder and update it. We welcome
new/updated translations, so feel free to contribute! To translate third party gems like devise, use for
example devise-i18n.
Namespaces
When registering resources in Active Admin, they are loaded into a namespace. The default namespace is
“admin”.
# app/admin/posts.rb
ActiveAdmin.register Post do
# ...
end
The Post resource will be loaded into the “admin” namespace and will be available at /admin/posts .
3 / 39
Each namespace holds on to its own settings that inherit from the application’s configuration.
For example, if you have two namespaces (:admin and :super_admin ) and want to have different site
title’s for each, you can use the config.namespace(name) block within the initializer file to configure
them individually.
ActiveAdmin.setup do |config|
config.site_title = "My Default Site Title"
Each setting available in the Active Admin setup block is configurable on a per namespace basis.
Load paths
By default Active Admin files go inside app/admin/. You can change this directory in the initializer file:
ActiveAdmin.setup do |config|
config.load_paths = [File.join(Rails.root, "app", "ui")]
end
Comments
By default Active Admin includes comments on resources. Sometimes, this is undesired. To disable
comments:
# For the entire application:
ActiveAdmin.setup do |config|
config.comments = false
end
# For a namespace:
ActiveAdmin.setup do |config|
config.namespace :admin do |admin|
admin.comments = false
end
end
You can change the name under which comments are registered:
config.comments_registration_name = 'AdminComment'
You can change the order for the comments and you can change the column to be used for ordering:
config.comments_order = 'created_at ASC'
You can disable the menu item for the comments index page:
config.comments_menu = false
4 / 39
Utility Navigation
The “utility navigation” shown at the top right normally shows the current user and a link to log out.
However, the utility navigation is just like any other menu in the system; you can provide your own menu
to be rendered in its place.
ActiveAdmin.setup do |config|
config.namespace :admin do |admin|
admin.build_menu :utility_navigation do |menu|
menu.add label: "ActiveAdmin.info", url: "http://www.activeadmin.info",
html_options: { target: :blank }
admin.add_current_user_to_menu menu
admin.add_logout_button_to_menu menu
end
end
end
Footer Customization
By default, Active Admin displays a “Powered by ActiveAdmin” message on every page. You can
override this message and show domain-specific messaging:
config.footer = "MyApp Revision v1.3"
5 / 39
Working with Resources
Every Active Admin resource corresponds to a Rails model. So before creating a resource you must first
create a Rails model for it.
Create a Resource
The basic command for creating a resource is rails g active_admin:resource Post . The generator
will produce an empty app/admin/post.rb file like so:
ActiveAdmin.register Post do
# everything happens here :D
end
Any form field that sends multiple values (such as a HABTM association, or an array attribute) needs to
pass an empty array to permit_params:
Nested associations in the same form also require an array, but it needs to be filled with any attributes
used.
ActiveAdmin.register Post do
permit_params :title, :content, :publisher_id,
tags_attributes: [:id, :name, :description, :_destroy]
end
If you want to dynamically choose which attributes can be set, pass a block:
ActiveAdmin.register Post do
permit_params do
params = [:title, :content, :publisher_id]
params.push :author_id if current_user.admin?
params
end
end
The permit_params call creates a method called permitted_params. You should use this method when
overriding create or update actions:
6 / 39
ActiveAdmin.register Post do
controller do
def create
# Good
@post = Post.new(permitted_params[:post])
# Bad
@post = Post.new(params[:post])
if @post.save
# ...
end
end
end
end
# Available at /posts
ActiveAdmin.register Post, namespace: false
7 / 39
The menu method accepts a hash with the following options:
:label - The string or proc label to display in the menu. If it’s a proc, it will be called each time the
menu is rendered.
:parent - The string id (or label) of the parent used for this menu
:if - A block or a symbol of a method to call to decide if the menu item should be displayed
:priority - The integer value of the priority, which defaults to 10
Labels
To change the name of the label in the menu:
ActiveAdmin.register Post do
menu label: "My Posts"
end
Menu Priority
Menu items are sorted first by their numeric priority, then alphabetically. Since every menu by default has
a priority of 10, the menu is normally alphabetical.
The proc will be called in the context of the view, so you have access to all your helpers and current user
session information.
Note that the “Blog” parent menu item doesn’t even have to exist yet; it can be dynamically generated for
you.
8 / 39
# config/initializers/active_admin.rb
config.namespace :admin do |admin|
admin.build_menu do |menu|
menu.add label: 'Blog', priority: 0
end
end
# app/admin/post.rb
ActiveAdmin.register Post do
menu parent: 'Blog'
end
# app/admin/post.rb
ActiveAdmin.register Post do
menu parent: 'blog'
end
This will be registered on application start before your resources are loaded.
Eager loading
A common way to increase page performance is to elimate N+1 queries by eager loading associations:
ActiveAdmin.register Post do
includes :author, :categories
end
If you need to customize the collection properties, you can overwrite the scoped_collection method.
ActiveAdmin.register Post do
controller do
def scoped_collection
end_of_association_chain.where(visibility: true)
end
end
end
If you need to completely replace the record retrieving code (e.g., you have a custom to_param
implementation in your models), override the resource method on the controller:
ActiveAdmin.register Post do
controller do
def find_resource
scoped_collection.where(id: params[:id]).first!
end
end
end
Note that if you use an authorization library like CanCan, you should be careful to not write code like this,
otherwise your authorization rules won’t be applied:
ActiveAdmin.register Post do
controller do
def find_resource
Post.where(id: params[:id]).first!
end
end
end
Belongs To
It’s common to want to scope a series of resources to a relationship. For example a Project may have many
Milestones and Tickets. To nest the resource within another, you can use the belongs_to method:
ActiveAdmin.register Project
ActiveAdmin.register Ticket do
belongs_to :project
end
10 / 39
Projects will be available as usual and tickets will be available by visiting /admin/projects/1/tickets
assuming that a Project with the id of 1 exists. Active Admin does not add “Tickets” to the global
navigation because the routes can only be generated when there is a project id.
To create links to the resource, you can add them to a sidebar (one of the many possibilities for how you
may with to handle your user interface):
ActiveAdmin.register Project do
ActiveAdmin.register Ticket do
belongs_to :project
end
ActiveAdmin.register Milestone do
belongs_to :project
end
In some cases (like Projects), there are many sub resources and you would actually like the global
navigation to switch when the user navigates “into” a project. To accomplish this, Active Admin stores the
belongs_to resources in a separate menu which you can use if you so wish. To use:
ActiveAdmin.register Ticket do
belongs_to :project
navigation_menu :project
end
ActiveAdmin.register Milestone do
belongs_to :project
navigation_menu :project
end
Now, when you navigate to the tickets section, the global navigation will only display “Tickets” and
“Milestones”. When you navigate back to a non-belongs_to resource, it will switch back to the default
menu.
You can also defer the menu lookup until runtime so that you can dynamically show different menus, say
perhaps based on user permissions. For example:
ActiveAdmin.register Ticket do
belongs_to :project
navigation_menu do
authorized?(:manage, SomeResource) ? :project : :restricted_menu
end
end
If you still want your belongs_to resources to be available in the default menu and through non-nested
routes, you can use the :optional option. For example:
ActiveAdmin.register Ticket do
belongs_to :project, optional: true
end
11 / 39
Customizing the Index Page
Filtering and listing resources is one of the most important tasks for administering a web application.
Active Admin provides many different tools for you to build a compelling interface into your data for the
admin staff.
Table: A table drawn with each row being a resource (View Table Docs)
Grid: A set of rows and columns each cell being a resource (View Grid Docs)
Blocks: A set of rows (not tabular) each row being a resource (View Blocks Docs)
Blog: A title and body content, similar to a blog index (View Blog Docs)
All index pages also support scopes, filters, pagination, action items, and sidebar sections.
The first index component will be the default index page unless you indicate otherwise by setting
:default to true.
index do
column :image_title
actions
end
index as: :grid, default: true do |product|
link_to image_tag(product.image_path), admin_product_path(product)
end
Custom Index
Active Admin does not limit the index page to be a table, block, blog or grid. If you’ve created your own
custom index page it can be included by setting :as to the class of the index component you created.
index as: ActiveAdmin::Views::IndexAsMyIdea do
column :image_title
actions
end
Index Filters
By default the index screen includes a “Filters” sidebar on the right hand side with a filter for each
attribute of the registered model. You can customize the filters that are displayed as well as the type of
widgets they use.
12 / 39
To display a filter for an attribute, use the filter method
ActiveAdmin.register Post do
filter :title
end
Out of the box, Active Admin supports the following filter types:
By default, Active Admin will pick the most relevant filter based on the attribute type. You can force the
type by passing the :as option.
filter :author, as: :check_boxes
The :check_boxes and :select types accept options for the collection. By default it attempts to create a
collection based on an association. But you can pass in the collection as a proc to be called at render time.
filter :author, as: :check_boxes, collection: proc { Author.all }
Also, if you don’t need the select with the options ‘contains’, ‘equals’, ‘starts_with’ or ‘ends_with’ just
add the option to the filter name with an underscore.
For example:
filter :name_equals
# or
filter :name_contains
By default, Active Admin will try to use ActiveModel I18n to determine the label.
You can also filter on more than one attribute of a model using the Ransack search predicate syntax. If
using a custom search method, you will also need to specify the field type using :as and the label.
filter :first_name_or_last_name_cont, as: :string, label: "Name"
Filters can also be disabled for a resource, a namespace or the entire application.
You can also add a filter and still preserve the default filters:
preserve_default_filters!
filter :author
Or you can also remove a filter and still preserve the default filters:
preserve_default_filters!
remove_filter :id
Index Scopes
You can define custom scopes for your index page. This will add a tab bar above the index table to
quickly filter your collection on pre-defined scopes. There are a number of ways to define your scopes:
scope :all, default: true
Index pagination
You can set the number of records per page as default:
ActiveAdmin.setup do |config|
config.default_per_page = 30
end
You can set the number of records per page per resources:
ActiveAdmin.register Post do
config.per_page = 10
end
If you have a very large database, you might want to disable SELECT COUNT(*) queries caused by the
pagination info at the bottom of the page:
ActiveAdmin.register Post do
index pagination_total: false do
# ...
end
end
end
# For the entire application:
ActiveAdmin.setup do |config|
config.download_links = false
config.download_links = [:csv, :xml, :json, :pdf]
config.download_links = proc { current_user.can_view_download_links? }
end
Note: you have to actually implement PDF rendering for your action, ActiveAdmin does not provide this
feature. This setting just allows you to specify formats that you want to show up under the index
collection.
You’ll need to use a PDF rendering library like PDFKit or WickedPDF to get the PDF generation you
want.
15 / 39
Customizing the CSV format
Active Admin provides CSV file downloads on the index screen for each Resource. By default it will
render a CSV file with all the content columns of your registered model.
You can also set custom CSV settings for an individual resource:
ActiveAdmin.register Post do
csv force_quotes: true, col_sep: ';', column_names: false do
column :title
column(:author) { |post| post.author.full_name }
end
end
Or system-wide:
# config/initializers/active_admin.rb
# Set the CSV builder separator
config.csv_options = { col_sep: ';' }
# Force the use of quotes
config.csv_options = { force_quotes: true }
You can customize the filename by overriding csv_filename in the controller block.
ActiveAdmin.register User do
controller do
def csv_filename
'User Details.csv'
end
end
end
Streaming
By default Active Admin streams the CSV response to your browser as it’s generated. This is good
because it prevents request timeouts, for example the infamous H12 error on Heroku.
However if an exception occurs while generating the CSV, the request will eventually time out, with the
last line containing the exception message. CSV streaming is disabled in development to help debug these
exceptions. That lets you use tools like better_errors and web-console to debug the issue. If you want to
customize the environments where CSV streaming is disabled, you can change this setting:
# config/initializers/active_admin.rb
config.disable_streaming_in = ['development', 'staging']
16 / 39
Forms
Active Admin gives you complete control over the output of the form by creating a thin DSL on top of
Formtastic:
ActiveAdmin.register Post do
form title: 'A custom title' do |f|
inputs 'Details' do
input :title
input :published_at, label: "Publish Post At"
li "Created at #{f.object.created_at}" unless f.object.new_record?
input :category
end
panel 'Markup' do
"The following can be used in the content below..."
end
inputs 'Content', :body
para "Press cancel to return to the list without saving."
actions
end
end
Default
Resources come with a default form defined as such:
form do |f|
f.semantic_errors # shows errors on :base
f.inputs # builds an input field for every attribute
f.actions # adds the 'Submit' and 'Cancel' buttons
end
Partials
If you want to split a custom form into a separate partial use:
ActiveAdmin.register Post do
form partial: 'form'
end
You can also use the ActiveAdmin::FormBuilder as builder in your Formtastic Form for use the same
helpers are used in the admin file:
= semantic_form_for [:admin, @post], builder: ActiveAdmin::FormBuilder do |f|
= f.inputs "Details" do
= f.input :title
- f.has_many :taggings, sortable: :position, sortable_start: 1 do |t|
- t.input :tag
= f.actions
17 / 39
Nested Resources
You can create forms with nested models using the has_many method, even if your model uses has_one :
ActiveAdmin.register Post do
form do |f|
f.inputs 'Details' do
f.input :title
f.input :published_at, label: 'Publish Post At'
end
f.inputs 'Content', :body
f.inputs do
f.has_many :categories, heading: 'Themes',
allow_destroy: true,
new_record: false do |a|
a.input :title
end
end
f.inputs do
f.has_many :taggings, sortable: :position, sortable_start: 1 do |t|
t.input :tag
end
end
f.inputs do
f.has_many :comment,
new_record: 'Leave Comment',
allow_destroy: -> { |c| c.author?(current_admin_user) } do |b|
b.input :body
end
end
f.actions
end
end
The :allow_destroy option adds a checkbox to the end of the nested form allowing removal of the child
object upon submission. Be sure to set allow_destroy: true on the association to use this option. It is
possible to associate :allow_destroy with a string or a symbol, corresponding to the name of a child
object’s method that will get called, or with a Proc object. The Proc object receives the child object as a
parameter and should return either true or false.
The :heading option adds a custom heading. You can hide it entirely by passing false.
The :new_record option controls the visibility of the new record button (shown by default). If you pass a
string, it will be used as the text for the new record button.
The :sortable option adds a hidden field and will enable drag & drop sorting of the children. It expects
the name of the column that will store the index of each child.
The :sortable_start option sets the value (0 by default) of the first position in the list.
Datepicker
ActiveAdmin offers the datepicker input, which uses the jQuery UI datepicker. The datepicker input
accepts any of the options available to the standard jQueryUI Datepicker. For example:
form do |f|
f.input :starts_at, as: :datepicker,
datepicker_options: {
min_date: "2013-10-8",
max_date: "+3D"
}
18 / 39
max_date: "+1W +5D"
}
end
Displaying Errors
To display a list of all validation errors:
form do |f|
f.semantic_errors *f.object.errors.keys
# ...
end
Tabs
You can arrange content in tabs as shown below:
form do |f|
tabs do
tab 'Basic' do
f.inputs 'Basic Details' do
f.input :email
f.input :password
f.input :password_confirmation
end
end
tab 'Advanced' do
f.inputs 'Advanced Details' do
f.input :role
end
end
end
f.actions
end
19 / 39
Customize the Show Page
The show block is rendered within the context of the view and uses Arbre syntax.
With the show block, you can render anything you want.
ActiveAdmin.register Post do
show do
h3 post.title
div do
simple_format post.body
end
end
end
If you’d like to keep the default AA look, you can use attributes_table:
ActiveAdmin.register Ad do
show do
attributes_table do
row :title
row :image do |ad|
image_tag ad.image.url
end
end
active_admin_comments
end
end
You can also customize the title of the object in the show screen:
show title: :name do
# ...
end
20 / 39
Sidebar Sections
Sidebars allow you to put whatever content you want on the side the page.
sidebar :help do
"Need help? Email us at help@example.com"
end
This will generate a sidebar on every page for that resource. The first argument is used as the title, and can
be a symbol, string, or lambda.
If you want to conditionally display a sidebar section, use the :if option and pass it a proc which will be
rendered within the view context.
sidebar :help, if: proc{ current_admin_user.super_admin? } do
"Only for super admins!"
end
It’s possible to add custom class name to the sidebar parent element by passing class option:
sidebar :help, class: 'custom_class'
By default sidebars are positioned in the same order as they defined, but it’s also possible to specify their
position manually:
# will push Help section to the top (above default Filters section)
sidebar :help, priority: 0
21 / 39
Custom Controller Actions
Active Admin allows you to override and modify the underlying controller which is generated for you.
There are helpers to add collection and member actions, or you can drop right in to the controller and
modify its behavior.
Collection Actions
A collection action is a controller action which operates on the collection of resources. This method adds
both the action to the controller as well as generating a route for you.
end
Member Actions
A member action is a controller action which operates on a single resource.
For example, to add a lock action to a user resource, you would do the following:
ActiveAdmin.register User do
member_action :lock, method: :put do
resource.lock!
redirect_to resource_path, notice: "Locked!"
end
end
HTTP Verbs
The collection_action and member_action methods both accept the :method argument to set the HTTP
verb for the controller action and route.
Sometimes you want to create an action with the same name, that handles multiple HTTP verbs. In that
case, this is the suggested approach:
member_action :foo, method: [:get, :post] do
if request.post?
resource.update_attributes! foo: params[:foo] || {}
head :ok
else
render :foo
end
end
22 / 39
Rendering
Custom controller actions support rendering within the standard Active Admin layout.
ActiveAdmin.register Post do
# /admin/posts/:id/comments
member_action :comments do
@comments = resource.comments
# This will render app/views/admin/posts/comments.html.erb
end
end
If you would like to use the same view syntax as the rest of Active Admin, you can use the Arbre file
extension: .arb.
Page Titles
The page title for the custom action will be the translated version of the controller action name. For
example, a member_action named “upload_csv” will look up a translation key of
active_admin.upload_csv. If none are found, it defaults to the name of the controller action.
If this doesn’t work for you, you can always set the @page_title instance variable in your controller
action to customize the page title.
ActiveAdmin.register Post do
member_action :comments do
@comments = resource.comments
@page_title = "#{resource.title}: Comments" # Sets the page title
end
end
Action Items
To include your own action items (like the New, Edit and Delete buttons), add an action_item block. The
first parameter is just a name to identify the action, and is required. For example, to add a “View on site”
button to view a blog post:
action_item :view, only: :show do
link_to 'View on site', post_path(post) if post.published?
end
Actions items also accept the :if option to conditionally display them:
action_item :super_action,
only: :show,
if: proc{ current_admin_user.super_admin? } do
"Only display this to super admins on the show screen"
end
23 / 39
Modifying the Controller
The generated controller is available to you within the registration block by using the controller
method.
ActiveAdmin.register Post do
controller do
# This code is evaluated within the controller class
def define_a_method
# Instance method
end
end
end
24 / 39
Batch Actions
By default, the index page provides you a “Batch Action” to quickly delete records, as well as an API for
you to easily create your own. Note that if you override the default index, you must add
selectable_column back for batch actions to be usable:
index do
selectable_column
# ...
end
# app/admin/post.rb
ActiveAdmin.register Post do
# Resource level:
config.batch_actions = false
end
Modification
If you want, you can override the default batch action to do whatever you want:
ActiveAdmin.register Post do
batch_action :destroy do |ids|
redirect_to collection_path, alert: "Didn't really delete these!"
end
end
Removal
You can remove batch actions by simply passing false as the second parameter:
ActiveAdmin.register Post do
batch_action :destroy, false
25 / 39
end
Conditional display
You can control whether or not the batch action is available via the :if option, which is executed in the
view context.
ActiveAdmin.register Post do
batch_action :flag, if: proc{ can? :flag, Post } do |ids|
# ...
end
end
Confirmation prompt
You can pass a custom string to prompt the user with:
ActiveAdmin.register Post do
batch_action :destroy, confirm: "Are you sure??" do |ids|
# ...
end
end
If you pass a nested array, it will behave just like Formtastic would, with the first element being the text
displayed and the second element being the value.
batch_action :doit, form: {user: [['Jake',2], ['Mary',3]]} do |ids, inputs|
User.find(inputs[:user])
# ...
end
When you have dynamic form inputs you can pass a proc instead:
batch_action :doit, form: -> { {user: User.pluck(:name, :id)} } do |ids, inputs|
User.find(inputs[:user])
# ...
end
Under the covers this is powered by the JS ActiveAdmin.modal_dialog which you can use yourself:
26 / 39
if $('body.admin_users').length
$('a[data-prompt]').click ->
ActiveAdmin.modal_dialog $(@).data('prompt'), comment: 'textarea',
(inputs)=>
$.post "/admin/users/#{$(@).data 'id'}/change_state",
comment: inputs.comment, state: $(@).data('state'),
success: ->
window.location.reload()
Translation
By default, the name of the batch action will be used to lookup a label for the menu. It will lookup in
active_admin.batch_actions.labels.#{your_batch_action}.
So this:
ActiveAdmin.register Post do
batch_action :publish do |ids|
# ...
end
end
end
BTW
In order to perform the batch action, the entire Table, Grid, etc. is wrapped in a form that submits the IDs
of the selected rows to your batch_action.
Since nested <form> tags in HTML often results in unexpected behavior, you may need to modify the
custom behavior you’ve built using to prevent conflicts.
Specifically, if you are using HTTP methods like PUT or PATCH with a custom form on your index page this
may result in your batch action being PUTed instead of POSTed which will create a routing error. You can
27 / 39
get around this by either moving the nested form to another page or using a POST so it doesn’t override
the batch action. As well, behavior may vary by browser.
28 / 39
Custom Pages
If you have data you want on a standalone page that isn’t tied to a resource, custom pages provide you with
a familiar syntax and feature set:
a menu item
sidebars
action items
page actions
Anything rendered within content will be the main content on the page. Partials behave exactly the same
way as they do for resources:
# app/admin/calendar.rb
ActiveAdmin.register_page "Calendar" do
content do
render partial: 'calendar'
end
end
# app/views/admin/calendar/_calendar.html.arb
table do
thead do
tr do
%w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday].each &method(:th)
end
end
tbody do
# ...
end
end
29 / 39
# Available at /calendar
ActiveAdmin.register_page "Calendar", namespace: false
Belongs To
To nest the page within another resource, you can use the belongs_to method:
ActiveAdmin.register Project
ActiveAdmin.register_page "Status" do
belongs_to :project
end
Add a Sidebar
See the Sidebars documentation.
action_item :add do
link_to "Add Event", admin_calendar_add_event_path, method: :post
end
This defines the route /admin/calendar/add_event which can handle HTTP POST requests.
Clicking on the action item will reload page and display the message “Your event was added”
30 / 39
Decorators
Active Admin allows you to use the decorator pattern to provide view-specific versions of a resource.
Draper is recommended but not required.
To use decorator support without Draper, your decorator must support a variety of collection methods to
support pagination, filtering, etc. See this github issue discussion and this gem for more details.
Example usage
# app/models/post.rb
class Post < ActiveRecord::Base
# has title, content, and image_url
end
# app/decorators/post_decorator.rb
class PostDecorator < Draper::Decorator
delegate_all
def image
h.image_tag model.image_url
end
end
# app/admin/post.rb
ActiveAdmin.register Post do
decorate_with PostDecorator
index do
column :title
column :image
actions
end
end
Forms
By default, ActiveAdmin does not decorate the resource used to render forms. If you need ActiveAdmin to
decorate the forms, you can pass decorate: true to the form block.
ActiveAdmin.register Post do
decorate_with PostDecorator
form decorate: true do |f|
# ...
end
end
31 / 39
Arbre Components
Arbre allows the creation of shareable and extendable HTML components and is used throughout Active
Admin to create view components.
Text Node
Sometimes it makes sense to insert something into a registered resource like a non-breaking space or some
text. The text_node method can be used to insert these elements into the page inside of other Arbre
components or resource controller functions.
ActiveAdmin.register Post do
show do
panel "Post Details" do
attributes_table_for post do
row :id
row 'Tags' do
post.tags.each do |tag|
a tag, href: admin_post_path(q: {tagged_with_contains: tag})
text_node " ".html_safe
end
end
end
end
end
end
Panels
A panel is a component that takes up all available horizontal space and takes a title and a hash of attributes
as arguments. If a sidebar is present, a panel will take up the remaining space.
Columns
The Columns component allows you draw content into scalable columns. All you need to do is define the
number of columns and the component will take care of the rest.
Simple Columns
To create simple columns, use the columns method. Within the block, call the #column method to create a
new column.
columns do
column do
span "Column #1"
end
column do
span "Column #2"
end
32 / 39
end
By default, each column spans 1 column. The above layout would have 2 columns, the first being twice as
large as the second.
In the above example, the first column will not grow larger than 200px and will not shrink less than
100px.
Table For
Table For provides the ability to create tables like those present in index_as_table. It takes a collection
and a hash of options and then uses column to build the fields to show with the table.
table_for order.payments do
column(:payment_type) { |payment| payment.payment_type.titleize }
column "Received On", :created_at
column "Details & Notes", :payment_details
column "Amount", :amount_in_dollars
end
the column method can take a title as its first argument and data (:your_method ) as its second (or first if
no title provided). Column also takes a block.
Status tag
Status tags provide convenient syntactic sugar for styling items that have status. A common example of
where the status tag could be useful is for orders that are complete or in progress. status_tag takes a
status, like “In Progress”, and a hash of options. The status_tag will generate HTML markup that Active
Admin CSS uses in styling.
status_tag 'In Progress'
# => <span class='status_tag in_progress'>In Progress</span>
tab :inactive do
table_for orders.inactive do
...
end
end
end
34 / 39
Authorization Adapter
Active Admin offers the ability to define and use your own authorization adapter. If implemented, the
‘#authorized?’ will be called when an action is taken. By default, ‘#authorized?’ returns true.
end
config.authorization_adapter = "OnlyAuthorsAuthorization"
Authorization adapters can be configured per ActiveAdmin namespace as well, for example:
ActiveAdmin.setup do |config|
config.namespace :admin do |ns|
ns.authorization_adapter = "AdminAuthorization"
end
config.namespace :my do |ns|
ns.authorization_adapter = "DashboardAuthorization"
end
end
end
35 / 39
adapter to scope the resource’s collection. For example, you may want to centralize the scoping:
class OnlyMyAccount < ActiveAdmin::AuthorizationAdapter
end
All collections presented on Index Screens will be passed through this method and will be scoped
accordingly.
Action Types
By default Active Admin simplifies the controller actions into 4 actions:
:read - This controls if the user can view the menu item as well as the index and show screens.
:create - This controls if the user can view the new screen and submit the form to the create
action.
:update - This controls if the user can view the edit screen and submit the form to the update
action.
:destroy - This controls if the user can delete a resource.
index do
column :title
column '' do |post|
link_to 'Edit', admin_post_path(post) if authorized? :update, post
end
end
36 / 39
end
If you are implementing a custom controller action, you can use the #authorize! method to raise an
ActiveAdmin::AccessDenied exception.
ActiveAdmin.register Post do
end
To use the CanCan adapter, simply update the configuration in the Active Admin initializer:
config.authorization_adapter = ActiveAdmin::CanCanAdapter
You can also specify a method to be called on unauthorized access. This is necessary in order to prevent a
redirect loop that can happen if a user tries to access a page they don’t have permissions for (see #2081).
config.on_unauthorized_access = :access_denied
The method access_denied would be defined in application_controller.rb. Here is one example that
redirects the user from the page they don’t have permission to access to a resource they have permission to
access (organizations in this case), and also displays the error message in the browser:
class ApplicationController < ActionController::Base
protect_from_forgery
def access_denied(exception)
redirect_to admin_organizations_path, alert: exception.message
end
end
By default this will use the ability class named “Ability”. This can also be changed from the initializer:
config.cancan_ability_class = "MyCustomAbility"
Now you can simply use CanCan or CanCanCan the way that you would expect and Active Admin will
use it for authorization:
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
can :manage, Post
can :read, User
can :manage, User, id: user.id
37 / 39
can :read, ActiveAdmin::Page, name: "Dashboard", namespace_name: :admin
end
end
To view more details about the API’s, visit project pages of CanCan and CanCanCan.
To use the Pundit adapter, simply update the configuration in the Active Admin initializer:
config.authorization_adapter = ActiveAdmin::PunditAdapter
You can simply use Pundit the way that you would expect and Active Admin will use it for authorization.
Check Pundit’s documentation to set up Pundit in your application. If you want to use batch actions just
ensure that destroy_all? method is defined in your policy class. You can use this template policy in your
application instead of default one generated by Pundit’s rails g pundit:install command.
38 / 39
39 / 39