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]
add_column :posts, :comments_count, :integer, default: 0
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
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 post
If we have multiple records we can use a loop
Post.all.each do |p|
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.