Add A Custom Computed Column To An Activeadmin Index Page
The default ActiveAdmin index lists raw columns. Real admin screens need derived values — a total from associated rows, a status badge, a link to a related record — and the column block gives you that.
Description
Inside index do ... end, column :name renders an attribute and column("Label") { |record| ... } renders whatever the block returns. The block runs in the view context, so link helpers, number_to_currency, and status_tag all work.
The trap is N+1 queries. Every block that touches an association fires a query per row, and an admin index showing thirty rows becomes thirty-one queries. Set includes on the controller scope to fix it.
A computed column is not sortable by default, since there is no column for SQL to order by. Pass sortable: :some_column when a real column can stand in for it.
Sample input:
column("Total") { |order| number_to_currency(order.total_cents / 100.0) }
Sample Output:
| ID | Customer | Items | Total | Status |
| 42 | Acme Corp | 3 | $425.00 | Confirmed |
Answer
ActiveAdmin.register Order do
# Fixes the N+1 that the blocks below would otherwise cause
controller do
def scoped_collection
super.includes(:customer, :line_items)
end
end
index do
selectable_column
id_column
column :customer, sortable: "customers.name" do |order|
link_to order.customer.name, admin_customer_path(order.customer)
end
column("Items") { |order| order.line_items.size }
column("Total", sortable: :total_cents) do |order|
number_to_currency(order.total_cents / 100.0, unit: order.currency_symbol)
end
column :status do |order|
status_tag order.status,
class: (order.cancelled? ? :error : :ok)
end
column("Age") { |order| "#{time_ago_in_words(order.created_at)} ago" }
actions
end
# Same idea on the show page
show do
attributes_table do
row :customer
row("Total") { |o| number_to_currency(o.total_cents / 100.0) }
end
end
end
Check viewARU - Brand Newsletter!
Newsletter to DEVs by DEVs - boost your Personal Brand & career! 🚀