Ruby
Customize ActiveAdmin Index Filters
ActiveAdmin allows us to quickly bootstrap an admin interface to our application. One of the features we get out of the box is a robust, comprehensive filtering sidebar. When viewing a resource's index page with hundreds of records, filtering allows us to narrow down to a digestible subset.
Unfortunately, the set of filters generated by ActiveAdmin for a particular model can sometimes be a bit hairy. If there are lots of fields and associations, you can end up with way more filters than you need, detracting from the user experience.
One solution is to remove the filters altogether.
ActiveAdmin.register Post do
config.filters = false
end
This is a bit drastic though. Perhaps we can find some middle ground by customizing the filters a bit. In the rest of this post, I'll layout some approaches we can take to make our filters cleaner and more directed.
Table of Contents
- Remove Specific Filters
- Declare Specific Filters
- Change A Filter's Label
- Scope A Filter's Collection
- Change The String Representation
- Coerce The Input Type
- Specify HTML Attributes
- Go Beyond
Remove Specific Filters
Often times the majority of the filters ActiveAdmin produces are fine. There are only one or two that need to be removed. You can provide one or more attributes or associations to be excluded from the set of filters with the remove_filter
directive.
ActiveAdmin.register Post do
remove_filter :developer, :max_likes
end
Declare Specific Filters
Perhaps there are only a couple filters you'd like to include. The rest of them ought to be excluded. Instead of declaring a large list of filters to remove -- a list which may need to be updated as the model changes -- you can explicitly declare the filters you'd like. This works because, when adding a filter, all the default filters are removed.
ActiveAdmin.register Post do
filter :developer # association from `belongs_to`
end
If you aren't wanting to remove all the default filters when modifying a filter as we did in the above example, include the preserve_default_filters!
directive before your filter changes.
ActiveAdmin.register Post do
preserve_default_filters!
filter :developer
filter :max_likes, label: "Maximum Likes"
end
Change A Filter's Label
You can customize the label used by a particular filter -- just include the label
option with the preferred text.
ActiveAdmin.register Post do
filter :max_likes, label: "Maximum Likes"
end
If you are using i18n for your model's name elsewhere, you'll need to be mindful of that here as well.
Scope A Filter's Collection
The collection of things that are included in a drop down filter defaults to all of those things. For example, if we were to fully spell out the filter's default collection for our developer
association, it would look something like this.
ActiveAdmin.register Post do
preserve_default_filters!
filter :developer, collection: -> { Developer.all }
end
We can take advantage of that syntax to scope the collection in whatever way we would like. For example, to only include developers with at least one post, we can scope our developer
collection like so.
ActiveAdmin.register Post do
filter :developer, collection: -> {
Developer.preload(:posts).select { |dev| dev.posts.present? }
}
end
Change The String Representation
There are two scenarios in which you'll want to adjust the string representation of items in a drop down. The more common is when ActiveAdmin doesn't know how to represent an object, so it uses the fallback object representation (e.g. #<Klass:0x401b3998 ...>
). The other is when the existing string representation just isn't what you want. In either case, the simplest solution is to add or modify to_s
for the particular model. If we want to restrict our changes to the app/admin
directory, we can again adjust the collection.
ActiveAdmin.register Post do
filter :developer, collection: -> {
Developer.all.map { |dev| [dev.email, dev.id] }
}
end
In this case, I chose to display a developer's email instead of the default of their username. We have to provide a tuple with the string representation and the id
. We have to provide the id
for ActiveAdmin to be able to look up and filter by a particular developer.
Coerce The Input Type
ActiveAdmin does its best to infer the type of input that should be used for a particular attribute, but it doesn't always nail it on the head. We can use the :as
option to coerce the input type to something else that makes more sense. For example, a drop down with yes
and no
options would be better off as a couple check boxes. A field that is an integer would be easy to interact with using a number input.
ActiveAdmin.register Post do
filter :tweeted, as: :check_boxes
filter :max_likes, as: :number
end
Specify HTML Attributes
We can even go a step further by specifying some attributes of an input field using the input_html
option. For example, we can set the step
, min
, and max
of our number input like so.
ActiveAdmin.register Post do
filter :max_likes,
as: :number,
input_html: { step: 10, min: 0, max: 100 }
end
Go Beyond
All of the examples I have laid out in this post can, generally speaking, be mixed and matched. If you want to do something that I haven't explicitely laid out, just give it a try. The syntax for filters is pretty flexible, so try bending it in various ways to meet your needs.
The filter sidebar is powered by Ransack
and Formtastic
. Feel free to dig into those repositories for even more insight. To create filters that use completely custom search/filtering, I recommend reading about Using Ransackers and checking out this blog post.
Have fun and build the filters of your dreams!
Cover image by Guillaume Lebelt on Unsplash.com