Skip to content

Instantly share code, notes, and snippets.

@dcalixto
Forked from marcamillion/console.rb
Created April 12, 2018 22:20
Show Gist options
  • Save dcalixto/e0544be738fc111f4d733773cddf28ee to your computer and use it in GitHub Desktop.
Save dcalixto/e0544be738fc111f4d733773cddf28ee 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment