Currently, mongoid gem doesn't support counter_cache and here's my workaround for that. Offcourse, there might be more better versions available, but just wanted to share mine too :)
In config/initializers/mongoid_counter_cache.rb
extend ActiveSupport::Concern
# Enables AR counter_cache mechanism on all cols ending with '_count' in the document.
# Ex. Usage: in Photo model, add 'include Mongoid::CounterCache', after fields definition.
# NOTE:: for a column 'likes_count' to work, we should have 'Like' document, with 'photo' association.
included do
klass = self.to_s.downcase
cache_cols = self.fields.keys.select { |col| col.include?('_count') }
create_meth = "increment_counter_in_#{klass}"
destroy_meth = "decrement_counter_in_#{klass}"
cache_cols.each do |col|
modal = col.to_s.sub(/_count/, '').classify.constantize
modal.class_eval <<-STR
after_create '#{create_meth}'.to_sym
after_destroy '#{destroy_meth}'.to_sym
def #{create_meth}
modal = self.#{klass}
count = modal.#{col} + 1
modal.update_attribute('#{col}'.to_sym, count)
end
def #{destroy_meth}
modal = self.#{klass}
count = modal.#{col} - 1
modal.update_attribute('#{col}'.to_sym, count)
end
STR
end # cache_cols.each
end # included
end
end
In app/models/photo.rb
include Mongoid::CounterCache, after the field declarations.
That's it. You are good to go. All columns ending with '_count' will be managed, automatically (provided the regular rails conventions are followed, refer inline comments in the code block, above.)
In config/initializers/mongoid_counter_cache.rb
module Mongoid
module CounterCache
extend ActiveSupport::Concern
# Enables AR counter_cache mechanism on all cols ending with '_count' in the document.
# Ex. Usage: in Photo model, add 'include Mongoid::CounterCache', after fields definition.
# NOTE:: for a column 'likes_count' to work, we should have 'Like' document, with 'photo' association.
included do
klass = self.to_s.downcase
cache_cols = self.fields.keys.select { |col| col.include?('_count') }
create_meth = "increment_counter_in_#{klass}"
destroy_meth = "decrement_counter_in_#{klass}"
cache_cols.each do |col|
modal = col.to_s.sub(/_count/, '').classify.constantize
modal.class_eval <<-STR
after_create '#{create_meth}'.to_sym
after_destroy '#{destroy_meth}'.to_sym
def #{create_meth}
modal = self.#{klass}
count = modal.#{col} + 1
modal.update_attribute('#{col}'.to_sym, count)
end
def #{destroy_meth}
modal = self.#{klass}
count = modal.#{col} - 1
modal.update_attribute('#{col}'.to_sym, count)
end
STR
end # cache_cols.each
end # included
end
end
In app/models/photo.rb
include Mongoid::CounterCache, after the field declarations.
That's it. You are good to go. All columns ending with '_count' will be managed, automatically (provided the regular rails conventions are followed, refer inline comments in the code block, above.)
No comments:
Post a Comment