Created
February 11, 2011 10:21
-
-
Save potapuff/822173 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Inspired by Rails memoizable, but use Rails.cache for storing informations | |
# core object must have id, if memoizible method not static (designed for ActiveRecord) | |
# each params must have method 'to_s' or be ActiveRecord | |
# params lenght.to_s might be less then 120 symbols - hasing is big black hole! | |
module CacheMemoizable | |
def self.included(base) | |
base.extend ClassMethods | |
end | |
module ClassMethods | |
def cache_memoize(*symbols) | |
symbols.each do |symbol| | |
dynamic = static = false | |
if (dynamic = method_defined?(symbol)) | |
class_eval(aliases_body(symbol,'defined')) | |
end | |
if (static = method_exists?(symbol)) | |
instance_eval(aliases_body(symbol,'exists')) | |
end | |
raise("Can't find method #{symbol} at class #{self.to_s}") unless dynamic || static | |
end | |
end | |
private | |
def method_exists? symbol | |
methods.include? symbol.to_s | |
end | |
def aliases_body symbol, context | |
class_name = (context== 'defined') ? self.class.to_s : self.to_s | |
original_method = :"_cache_#{class_name}_#{symbol}" | |
<<-CODE | |
if method_#{context}?(:#{original_method}) | |
raise "Method #{symbol} already cached with CacheMemoized" | |
end | |
alias :#{original_method} :#{symbol} | |
def #{symbol}(*args) | |
reload = args.pop if args.last == true || args.last == :reload | |
arg_key = args.map {|x| (x.kind_of?(ActiveRecord)) ? x.class.to_s+'#'+x.id : (x.nil? ? 'nil' : x.to_s)}.join('_') | |
key = create_cahe_key_for_method '#{symbol}',*args | |
if reload || (value = Rails.cache.read(key)).nil? | |
value = self.#{original_method}(*args) | |
end | |
Rails.cache.write(key, value.nil? ? :empty_value : value) | |
(value == :empty_value) ? nil : value | |
end | |
unless method_#{context}?(:uncache_#{symbol}) | |
def uncache_#{symbol}(*args) | |
key = create_cahe_key_for_method '#{symbol}',*args | |
Rails.cache.write(key, nil) | |
end | |
end | |
unless method_#{context}?(:create_cahe_key_for_method) | |
def create_cahe_key_for_method method_name, *args | |
arg_key = args.map do |x| | |
if (x.kind_of?(ActiveRecord)) | |
x.class.to_s+'#'+x.id | |
else | |
(x.nil? ? 'nil' : x.to_s) | |
end | |
end.join('_') | |
key = method_name.to_s | |
key << id.to_s if ('#{context}' == 'defined') | |
key << ((arg_key.size+key.size<120) ? arg_key : arg_key.hash.to_s) | |
end | |
end | |
CODE | |
end | |
end | |
end | |
=begin | |
require 'cache_memoizable' | |
class Foo | |
include CacheMemoizable | |
def foo() rand end | |
def self.foo() rand end | |
cache_memoize :foo | |
end | |
Foo.foo # 1 | |
Foo.foo # 1 | |
foo = Foo.new | |
foo1= Foo.new | |
foo.foo # 2 | |
foo.foo # 2 | |
foo1.foo # 3 | |
foo.clear_foo #nil | |
foo.foo # 4 | |
foo.foo # 4 | |
Foo.foo # 1 | |
foo1.foo # 3 | |
=end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment