Skip to content

cedric/custom_counter_cache

Repository files navigation

This is a simple approach to creating a custom counter cache in Rails that can be used across multiple models.

  • Ruby >= 3.1

  • Rails >= 7.2

Add the following to your Gemfile:

gem 'custom_counter_cache'

This is the block that will be used to calculate the value for the counter cache. It will be called by other models through their association via an after_save or after_destroy callback.

include CustomCounterCache::Model
define_counter_cache :articles_count do |user|
  user.articles.where(state: 'published').count
end

This will define the after_create, after_update and after_destroy callbacks. An :if option can be provided to limit when these callbacks get triggered.

include CustomCounterCache::Model
update_counter_cache :user, :articles_count, if: -> (article) { article.state_changed? }

These callbacks can be added to any number of models that might need to change the counter cache.

To store the counter cache you need to create a column for the model with the counter cache (example: articles_count).

If you would like to store all of your counter caches in a single table, you can use this migration:

create_table :counters do |t|
  t.references :countable, polymorphic: true
  t.string :key, null: false
  t.integer :value, null: false, default: 0
  t.timestamps
end
add_index :counters, [ :countable_id, :countable_type, :key ], unique: true

Here is the example model to go with:

class Counter < ActiveRecord::Base
  belongs_to :countable, polymorphic: true
  validates :countable, presence: true
end

If you would like to store your counter cache in an existing table, you can use this migration:

def change
  add_column :users, :articles_count, :integer, default: 0, null: false
end

To backfill your counters, run something like this either in a migration or in the console:

User.select(:id).find_each(batch_size: 100) { |u| u.update_articles_count }

About

Custom counter_cache functionality that supports conditions and multiple models.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages