module CounterCacheRails::ActiveRecordExtention
Public Class Methods
counter_cache(tableized_model, options = {})
click to toggle source
Enable counter cache for a child association
@param tableized_model [Symbol] Name of the child association @param options [Hash] @option options [Proc] :if @option options [Proc] :unless @option options [Proc] :scope
# File lib/counter_cache_rails/active_record_extention.rb, line 15 def self.counter_cache(tableized_model, options = {}) class_name = self.to_s.downcase child_model_class = tableized_model.to_s.classify.constantize tableized_child_model = tableized_model.to_sym primary_key = self.primary_key.to_sym callback_names = %i(update increment decrement cache).each_with_object({}) do |name, hash| callback_name = "#{name}_#{tableized_child_model}_count".to_sym hash[name] = callback_name define_model_callbacks callback_name end define_method "#{tableized_child_model}_count" do |force: false| count = Rails.cache.read(_counter_cache_key(class_name, primary_key, tableized_child_model), raw: true) if count.nil? || force run_callbacks callback_names[:cache] do scope = options[:scope] ? options[:scope].call(self.send(tableized_child_model)) : self.send(tableized_child_model) count = scope.count Rails.cache.write( self._counter_cache_key(class_name, primary_key, tableized_child_model), count, raw: true, expires_in: CounterCacheRails.configuration.expires_in, ) end end count.to_i end define_method "_#{tableized_child_model}_count_incr" do run_callbacks callback_names[:update] do run_callbacks callback_names[:increment] do key = _counter_cache_key(class_name, primary_key, tableized_child_model) Rails.cache.exist?(key) ? Rails.cache.increment(key) : send("#{tableized_child_model}_count") end end end define_method "_#{tableized_child_model}_count_decr" do run_callbacks callback_names[:update] do run_callbacks callback_names[:decrement] do key = _counter_cache_key(class_name, primary_key, tableized_child_model) Rails.cache.exist?(key) ? Rails.cache.decrement(key) : send("#{tableized_child_model}_count") end end end after_create do scope = options[:scope] ? options[:scope].call(self.send(tableized_child_model)) : self.send(tableized_child_model) Rails.cache.write( self._counter_cache_key(class_name, primary_key, tableized_child_model), scope.count, raw: true ) end child_model_class.class_eval do after_create do next unless options[:if].nil? || options[:if].call(self) next if !options[:unless].nil? && options[:unless].call(self) self.send(class_name.to_sym).send("_#{tableized_child_model}_count_incr") end after_destroy do next unless options[:if].nil? || options[:if].call(self) next if !options[:unless].nil? && options[:unless].call(self) self.send(class_name.to_sym).send("_#{tableized_child_model}_count_decr") end end end
Public Instance Methods
_counter_cache_key(class_name, primary_key, tableized_child_model)
click to toggle source
# File lib/counter_cache_rails/active_record_extention.rb, line 92 def _counter_cache_key(class_name, primary_key, tableized_child_model) '_' + [class_name, self.send(primary_key), tableized_child_model].join('_') end