Legal stuff about this site and your private life:

  • We use a cookie to keep your preferences (language, NSFW status, login status) during navigation.
  • We use your local storage to save the announces you closed (like this one).
  • We don't save informations you don't give
  • We don't share your email address if you comment or register
  • There is no tracker of any kind.

If you're not OK with this, move your way.

Counter caches are really useful to keep a track of the amount of related data a given record has. Unfortunately, it's a delicate setup for has_and_belongs_to_many relations

I started to implement experimentslabs.com using Ruby on Rails for learning reasons, and I had a hard time implementing counter caches on has_and_belongs_to_many relations.

First, I tried with callbacks, but the after_destroy callback was not fired, so the counters were only growing up.

Then, I changed the relations to has_many through: :xxx, with the idea of putting the counter_cache declaration in the pivot table. Again, to callback fired on destoy (even with dependent: true). I hope this is not linked to this open issue from 2014 titling "Fails to invoke after_remove callback when deleting associated record"

During my research, I found this great post by jjmars, and I finally came to this solution:

# album.rb
class Album < ApplicationRecord
  has_many :albums_tags
  has_many :tags, through: :albums_tags, dependent: :destroy
end

# tag.rb, contains field "albums_count"
class Tag < ApplicationRecord
  has_many :albums_tags
  has_many :albums, through: :albums_tags
end

# albums_tag.rb
class AlbumsTag < ApplicationContentRecord
  belongs_to :album
  belongs_to :tag

  after_create :increment_counter_cache
  after_destroy :decrement_counter_cache

  private
  def increment_counter_cache
    tag.update(albums_count: (tag.albums_count + 1))
  end

  def decrement_counter_cache
    tag.update(albums_count: (tag.albums_count - 1))
  end
end

Hope this helps :)

Leave a comment

You want to react to this content or ask something to the author? Just leave a comment here!

Note that the comments are not publicly visible, so don't worry if you don't see yours.

All the information you give will only be visible to the author. We don't share anything with anyone.

Don't fill this field if you want this form to be saved.