Customizing your index and show pages
Customizing the #index
page
After generating the controller, we’ll need to update it by adding method called #display_schema
. It’ll return an instance of Super::Display
. Let’s start with Admin::ProductsController
.
class Admin::ProductsController < AdminController
private
def model
Product
end
def display_schema
Super::Display.new do |f, type|
end
end
end
Once you save that and reload the page, you won’t see any data columns, only an “Actions” column.
The f
variable is similar to a Hash where the key is the column name and the value is the rule we use to turn it into a human readable value.
With that in mind, let’s manually make it look like it used to.
def display_schema
Super::Display.new do |f, type|
f[:name] = type.string
f[:price_cents] = type.string
end
end
We see there that strangely, that the type for price_cents
is string
and not integer
. The string
here should be thought of as to_s
, not the actual type of the column.
It’s a little unnatural to show prices in cents; here where I live, we usually communicate in dollars. So let’s try formatting this a bit differently.
def display_schema
Super::Display.new do |f, type|
f[:name] = type.string
f[:price_cents] = type.real { |column_value| "$#{sprintf("%.2f", column_value)}" }
end
end
By choosing type.real
, we’re telling Super that :price_cents
is a database column and is thus filterable.
You’ll notice though that the name of the column still reads Price cents
. Here’s one way we can get around that.
def display_schema
Super::Display.new do |f, type|
f[:name] = type.string
f[:price] = type.computed(:record) { |record| "$#{sprintf("%.2f", record.price_cents)}" }
end
end
Since we’ve specified type.computed
here, Super knows not to attempt to search using the price
column. Both computed
and real
accept arguments which tell it what to yield into your block: :column
is the default and it yields the value of the column (it doesn’t have to be a column, just a method on the object), :record
yields the entire record itself, and :none
doesn’t yield anything.
Customizing the #show
page
Customizing this page is identical to the #index
page. However, #index
pages tend to highlight some important fields while the #show
page might show every field.
Let’s start with a controller that already has the #index
view set up.
class Admin::CustomersController < AdminController
private
def model
Customer
end
def display_schema
Super::Display.new do |f, type|
f[:name] = type.string
if current_action.show?
f[:receipt_count] = f.computed(:record) { |record| record.receipts.size }
end
end
end
end
To add a field to only the #show
page, we’ll use the #current_action
method that’s already defined in the controller. With this, we can specify what data to show in the different pages.
def display_schema
Super::Display.new do |f, type|
f[:name] = type.string
if current_action.show?
f[:receipt_count] = f.computed(:record) { |record| record.receipts.size }
end
end
end
Showing a field on only the #index
page is similar too, you can check for current_action.index?
.
Note that this is just Ruby, so if you define a method like #current_admin
, you can show some fields to some users while hiding it for others. You can customize this however you wish!
Supported display types
#real
#computed
#string
#timestamp
#time
#rich_text
(ActionText)#badge
#actions