Skip to content

Instantly share code, notes, and snippets.

@marcamillion
Created March 27, 2013 15:50
Show Gist options
  • Save marcamillion/5255300 to your computer and use it in GitHub Desktop.
Save marcamillion/5255300 to your computer and use it in GitHub Desktop.
Implementing HABTM counter_cache - between 2 models (Tag, Question)
## I imagine this could be done in the migration, but it was giving me problems so I moved it to the model
## and just did it on the command line
> Tag.reset_questions_count
class AddTagCounterToQuestion < ActiveRecord::Migration
def up
add_column :tags, :questions_count, :integer, default: 0, null: false
end
def down
remove_column :tags, :questions_count
end
end
class Question < ActiveRecord::Base
## the validates_tag method is just to prevent duplicate tags being added to the db - not fully necessary for this exercise,
## but I figured I would leave it just in case
has_and_belongs_to_many :tags, before_add: :validates_tag
after_create :increment_tags_counter
after_destroy :decrement_tags_counter
def validates_tag(tag)
self.tags.include? tag
end
def increment_tags_counter
self.tags.each do |t|
Tag.find_by_name(t.name).questions_count += 1
end
end
## I haven't tested the callback on this, but it should work. What I am not 100% sure of is if the record is saved even
## a destroy, such that we can call `self.tags` on that same record and it works. If it doesn't work, then this can just
## be moved to a 'before_destroy'.
def decrement_tags_counter
self.tags.each do |t|
Tag.find_by_name(t.name).questions_count -= 1
end
end
end
class Tag < ActiveRecord::Base
attr_accessible :name, :questions_count
has_and_belongs_to_many :questions, uniq: true
def self.reset_questions_count
Tag.all.each do |t|
question_count = t.questions.count
t.update_attributes(:questions_count => question_count)
end
end
end
@asiniy
Copy link

asiniy commented Jan 12, 2015

This isn't a good code. Rails should do it automatically

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment