Rails foundationSort Order

Rails: Solving N+1 with Counter Cache

Counter cache is another way of solving N+1 problem. It solves the problem by incrementing a column in the database. Let's begin by creating the migration file.

Generating the Migration

rails g migration AddCommentsCountToPosts
class AddCommentsCountToPosts < ActiveRecord::Migration[5.2]  def change    add_column :posts, :comments_count, :integer, default: 0  endend

The comments_count column will be used by the Comment model to track the count of the comments. This means we need to add a setting on our belongs_to relationship.

Adding the Counter Cache Option

class Comment < ApplicationRecord  belongs_to :post, counter_cache: true  # ..end

If we use the default naming convention of the counter cache by using the [name_of_relationship]s_count this setting will work just fine, however if we define a custom column name in our migration we need to change true to the name of the field in the database.

For example, in your migration if you named your column :count_of_comments you will need to use this name at the belongs_to :post, counter_cache: :count_of_comments .

Calling the Cache in the View

Once we setup our database and model we need to call it in the view. Instead of just using post.comments.count we need to switch to post.comments_count now it will use the counter cache instead of calling count on the database.

Updating Older Records

Many times you will need to update the counter cache of existing records, there is a utility function we can call.

# 1 is the id of the postPost.reset_counters(1, :comments)

If we have multiple records we can use a loop

Post.all.each do |p|  Post.reset_counters(p.id, :comments)end

That's it for counter caches! Knowing these simple techniques can go a long way in ensuring that your application doesn't slow to a crawl. Working with Rails we have to be mindful about how the queries are being generated by ActiveRecord to ensure that our application stays performant.