module CustomCounterCache::Model::ClassMethods
Public Instance Methods
define_counter_cache(cache_column, &block)
click to toggle source
# File lib/custom_counter_cache/model.rb, line 7 def define_counter_cache(cache_column, &block) return unless table_exists? # counter accessors unless column_names.include?(cache_column.to_s) has_many :counters, as: :countable, dependent: :destroy define_method "#{cache_column}" do # check if the counter is loaded if counters.loaded? && counter = counters.detect{|c| c.key == cache_column.to_s } counter.value else counters.find_by_key(cache_column.to_s).try(:value).to_i end end define_method "#{cache_column}=" do |count| if ( counter = counters.find_by_key(cache_column.to_s) ) counter.update_attribute :value, count.to_i else counters.create key: cache_column.to_s, value: count.to_i end end end # counter update method define_method "update_#{cache_column}" do if self.class.column_names.include?(cache_column.to_s) update_attribute cache_column, block.call(self) else send "#{cache_column}=", block.call(self) end end rescue StandardError => e # Support Heroku's database-less assets:precompile pre-deploy step: raise e unless ENV['DATABASE_URL'].to_s.include?('//user:pass@127.0.0.1/') end
update_counter_cache(association, cache_column, options = {})
click to toggle source
# File lib/custom_counter_cache/model.rb, line 44 def update_counter_cache(association, cache_column, options = {}) return unless table_exists? association = association.to_sym cache_column = cache_column.to_sym method_name = "callback_#{association}_#{cache_column}".to_sym reflection = reflect_on_association(association) foreign_key = reflection.try(:foreign_key) || reflection.association_foreign_key # define callback define_method method_name do # update old association rails_5_1_or_newer = ActiveModel.version >= Gem::Version.new('5.1.0') target_key = reflection.options[:polymorphic] ? "#{association}_type" : foreign_key target_changed = rails_5_1_or_newer ? send("saved_change_to_#{target_key}?") : send("#{target_key}_changed?") if target_changed old_id = rails_5_1_or_newer ? send("#{target_key}_before_last_save") : send("#{target_key}_was") klass = if reflection.options[:polymorphic] ( old_id || send("#{association}_type") ).constantize else reflection.klass end if ( old_id && record = klass.find_by(id: old_id) ) record.send("update_#{cache_column}") end end # update new association if ( record = send(association) ) record.send("update_#{cache_column}") end end skip_callback = Proc.new { |callback, opts| (opts[:except].present? && opts[:except].include?(callback)) || (opts[:only].present? && !opts[:only].include?(callback)) } # set callbacks after_create method_name, options unless skip_callback.call(:create, options) after_update method_name, options unless skip_callback.call(:update, options) after_destroy method_name, options unless skip_callback.call(:destroy, options) rescue StandardError => e # Support Heroku's database-less assets:precompile pre-deploy step: raise e unless ENV['DATABASE_URL'].to_s.include?('//user:pass@127.0.0.1/') end