Rails 7.1 Introduces By Argument For increment_counter And decrement_counter Methods.

Counter caching is a common practice in Rails, used to keep track of counts such as the number of comments on a post or likes on a video. Rails 7.1 provides built-in methods like increment_counter and decrement_counter for updating counters without loading records into memory. However, before Rails 7.1, these methods could only update by a value of 1.

In scenarios where counter caches needed to be incremented or decremented by amounts greater than 1, such as recalculating counts or applying bulk updates, we often turned to workarounds or relied on gems like counter_culture. With the introduction of the by argument in Rails 7.1, managing these cases is now much simpler.

Before Rails 7.1:

By default, increment_counter and decrement_counter only supported updates by 1. To increment or decrement by custom amounts, we had to:

1) Use Raw SQL:

Article.where(id: 10).update_all("comments_count = comments_count + 5")

This was efficient but required direct SQL manipulation, reducing code clarity.

2) Fetch and Update the Record:

article = Article.find(10)
article.increment(:comments_count, 5)
article.save

While more readable, this approach was less performant, especially for bulk updates.

3) Rely on Gems like counter_culture:

The counter_culture gem was widely used for advanced counter caching scenarios, such as conditional counters or updates across associations:

class Comment < ApplicationRecord
  belongs_to :article
  counter_culture :article, column_name: 'comments_count'
end

Comment.counter_culture_fix_counts # Count all Comment records associated with each Article

Although powerful, introducing external dependencies added complexity.

After Rails 7.1:

Rails 7.1 allows increment_counter and decrement_counter to accept a by argument, allowing updates by any amount in a single, clean line of code. We simply pass the desired number as the by argument.

Incrementing a Counter:

Article.increment_counter(:comments_count, 10, by: 5)

This will increase the comments_count column of the record with id: 10 by 5.

Decrementing a Counter:

Article.decrement_counter(:comments_count, 10, by: 3)

This will decrease the comments_count column of the record with id: 10 by 3.

Need help on your Ruby on Rails or React project?

Join Our Newsletter