/ RAILS

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
  end

Post

  class Post
    belongs_to :user
  end

Register a model with ActiveAdmin

A model can be registered with ActiveAdmin with the help of command,

rails generate active_admin:resource Post

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,

index do
  column :title
  column :description
  column :user
  id_column
  actions
end

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,

  controller do
    def scoped_collection
      super.includes :user
    end
  end

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.

akshay

Akshay Mohite

Hi there! I am a Ruby on Rails & ReactJS Enthusiast, building some cool products at DTree Labs.

Read More
Buy me a coffee