Module: ActiveCacher

Defined in:
lib/active_cacher.rb,
lib/active_cacher/version.rb

Overview

Module for caching results of method invocations. It’s used as follows:

class A

prepend ActiveCacher.instance
instance_cache :foo_a, :foo_b
rails_cache :foo_c

 def foo_a
   # some code
 end
 def foo_b
   # some code
 end
 def foo_c
   # some code
 end

end

Here return values of method calls ‘foo_a’ and ‘foo_b’ will be cached into instance variables ‘@_foo_a’ and ‘@__foo_b’ while result of method call ‘foo_c’ will be both cached into instance variable ‘@_foo_c’ and written to Rails cache.

Calling ‘instance_cache :foo_a’ is roughly equivalent to the following code:

def foo_a

@__foo_a ||= begin
  # some code
end

end

And calling ‘rails_cache :foo_c’ is roughly equivalent to the following code:

def foo_c

@__foo_c ||= Rails.cache.fetch [self, :foo_c] do
  # some code
end

end

Constant Summary collapse

VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.instanceObject

It’s important to prepend module’s clone (obtained with ‘instance’ class method) instead of module itself since decorated methods are defined in ActiveCacher module and prepending ActiveCacher in multiple classes might result into method name clashes with unpredictable consequences.



47
48
49
50
51
# File 'lib/active_cacher.rb', line 47

def self.instance
  cloned = clone
  cloned.instance_variable_set "@cloned", true
  cloned
end

.prepended(target) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/active_cacher.rb', line 53

def self.prepended target
  raise "do not prepend ActiveCacher - prepend ActiveCacher.instance instead" unless @cloned
  cacher = self

  target.send :define_singleton_method, :instance_cache do |*methods|
    methods.each do |method|
      escaped_method = method.to_s.include?('?') ? "is_#{method[0..-2]}" : method

      cacher.send :define_method, method do |*args|
        instance_variable_get("@__#{escaped_method}") ||
          instance_variable_set("@__#{escaped_method}", prepare_for_cache(super(*args)))
      end
    end
  end

  if defined?(Rails)
    target.send :define_singleton_method, :rails_cache do |*methods|
      methods.each do |method|
        escaped_method = method.to_s.include?('?') ? "is_#{method[0..-2]}" : method

        cacher.send :define_method, method do |*args|
          instance_variable_get("@__#{escaped_method}") ||
            instance_variable_set("@__#{escaped_method}", Rails.cache.fetch([cache_key_object, method], expires_in: 2.weeks) { prepare_for_cache(super(*args)) })
        end
      end
    end
  end
end