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
class User
has_many :posts
endPost
class Post
belongs_to :user
endRegister a model with ActiveAdmin
A model can be registered with ActiveAdmin with the help of command,
rails generate active_admin:resource Postwhere 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,
index do
column :title
column :description
column :user
id_column
actions
endThe 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,
controller do
def scoped_collection
super.includes :user
end
endThis 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
