Rails ActiveAdmin N+1 query optmization for controller actions
ActiveAdmin is one of the most used Admin interface with the Rails applications. It provides an easy way to view, create, update or destroy records. When a model is registered with ActiveAdmin, it may have associations. In that case, when index page is opened for the model, it fires N+1 queries to fetch the values of an associated class. This presents performance bottleneck. This article will help remove N+1 querying on ActiveAdmin controller index action for a model.
Schema
Let’s say we have a few tables in our database just to demonstrate the N+1 problem on index action. Then, we see how we can solve it using eager loading.
User
Post
Register a model with ActiveAdmin
A model can be registered with ActiveAdmin with the help of command,
where Post
is the model name.
The above command will create an activeadmin configuration file
for the post resource in app/admin/post.rb
.
This file holds what all details to be included
to view, create, update, delete post records.
The post admin page can be accessed at
/admin/post
.
Refer getting started on ActiveAdmin to register a resource.
Add index page attributes
Attributes that need be displayed for Post
records can be defined in
the app/admin/post.rb
file.
Refer customizing index page action on ActiveAdmin.
Let us use index as a table layout
for rendering Post
records on the index page.
Example,
The above code tell ActiveAdmin
to show id
, title
, description
and user
attributes
for each Post
record on index action.
N+1 query on User
When /admin/post
page is opened,
ActiveAdmin looks up attributes required
for the index action.
It sees
- id
- title
- description
- user
It can get id
, title
, description
attributes in the same Post
table.
When getting user
, it tries to fetch name of the user
.
This is called on each post
record.
It adds up an extra query to get the user corresponding to a post.
Optimize N+1 query with Eager Loading
Eager loading comes to rescue N+1 querying on such controller index actions
on ActiveAdmin.
We can use Model.includes(:association)
to eager load association
records
when fetching Model
records.
In order to eager load for the index
action of ActiveAdmin,
we can use code given below,
This scoped_collection
is used to pass in to ActiveAdmin views
that are rendered for the index
action.
Here, eager loading user
attributes solves the N+1 querying problem.
includes
can alse be used to load multiple associations if your
model has many or belongs to associations.
Subscribe to Ruby in Rails
Get the latest posts delivered right to your inbox