class ActiveModelCachers::ActiveRecord::Cacher

Public Class Methods

define_cacher_method(attr, primary_key, service_klasses) click to toggle source
# File lib/active_model_cachers/active_record/cacher.rb, line 12
def define_cacher_method(attr, primary_key, service_klasses)
  cacher_klass = get_cacher_klass(attr.klass)
  method = attr.column
  return cacher_klass.define_find_by(attr, primary_key, service_klasses) if method == nil
  cacher_klass.send(:define_methods, method, {
    method            => ->{ exec_by(attr, primary_key, service_klasses, :get) },
    "peek_#{method}"  => ->{ exec_by(attr, primary_key, service_klasses, :peek) },
    "clean_#{method}" => ->{ exec_by(attr, primary_key, service_klasses, :clean_cache) },
  })
end
define_find_by(attr, primary_key, service_klasses) click to toggle source
# File lib/active_model_cachers/active_record/cacher.rb, line 23
def define_find_by(attr, primary_key, service_klasses)
  if @find_by_mapping == nil
    @find_by_mapping = {}
    define_methods(:find_by, {
      :find_by   => ->(args){ exec_find_by(args, :get) },
      :peek_by   => ->(args){ exec_find_by(args, :peek) },
      :clean_by  => ->(args){ exec_find_by(args, :clean_cache) },
    })
  end
  @find_by_mapping[primary_key] = [attr, service_klasses]
end
get_cacher_klass(klass) click to toggle source
# File lib/active_model_cachers/active_record/cacher.rb, line 8
def get_cacher_klass(klass)
  @defined_map[klass] ||= create_cacher_klass_at(klass)
end
new(id: nil, model: nil) click to toggle source
# File lib/active_model_cachers/active_record/cacher.rb, line 65
def initialize(id: nil, model: nil)
  @id = id
  @model = model
end

Private Class Methods

create_cacher_klass_at(target) click to toggle source
# File lib/active_model_cachers/active_record/cacher.rb, line 51
def create_cacher_klass_at(target)
  cacher_klass = Class.new(self)
  cacher_klass.instance_variable_set(:@find_by_mapping, nil) # to remove warning: instance variable @find_by_mapping not initialized
  cacher_klass.define_singleton_method(:attributes){ @attributes ||= [] }
  cacher_klass.send(:define_method, 'peek'){|column| send("peek_#{column}") }
  cacher_klass.send(:define_method, 'clean'){|column| send("clean_#{column}") }

  target.define_singleton_method(:cacher_at){|id| cacher_klass.new(id: id) }
  target.define_singleton_method(:cacher){ cacher_klass.new }
  target.send(:define_method, :cacher){ cacher_klass.new(model: self) }
  return cacher_klass
end
define_methods(attribute, methods_mapping) click to toggle source
# File lib/active_model_cachers/active_record/cacher.rb, line 37
def define_methods(attribute, methods_mapping)
  if attributes.include?(attribute)
    methods_mapping.keys.each{|s| undef_method(s) }
  else
    attributes << attribute
  end
  methods_mapping.each{|method, block| define_method(method, &block) }
end
get_data_from_find_by_mapping(primary_key) click to toggle source
# File lib/active_model_cachers/active_record/cacher.rb, line 46
def get_data_from_find_by_mapping(primary_key)
  return if @find_by_mapping == nil
  return @find_by_mapping[primary_key]
end

Private Instance Methods

exec_by(attr, primary_key, service_klasses, method, data: nil) click to toggle source
# File lib/active_model_cachers/active_record/cacher.rb, line 79
def exec_by(attr, primary_key, service_klasses, method, data: nil)
  bindings = [@model]
  reflects = (attr.belongs_to? ? [] : [attr.reflect])
  if @model and attr.association?
    if attr.belongs_to? and method != :clean_cache # no need to load binding when just cleaning cache
      association = @model.association(attr.column)
      bindings << association.load_target if association.loaded?
    end
  end
  data ||= (@model ? @model.send(primary_key) : nil) || @id
  service_klasses.each_with_index do |service_klass, index|
    data = service_klass.instance(data).send(method, binding: bindings[index], reflect: reflects[index])
    return if data == nil
  end
  return data
end
exec_find_by(args, method) click to toggle source
# File lib/active_model_cachers/active_record/cacher.rb, line 72
def exec_find_by(args, method) # e.g. args = {course_id: xx}
  primary_key = args.keys.sort.first # Support only one key now.
  attr, service_klasses = self.class.send(:get_data_from_find_by_mapping, primary_key)
  return if service_klasses == nil
  return exec_by(attr, primary_key, service_klasses, method, data: args[primary_key])
end