我想造一个方法,使用方法是这样的
class User < ActiveRecord::Base
redis_cache 10 do
def self.aaa
'it works'
end
def bbb
'it works'
end
end
end
我想实现的效果是,包裹在 redis_cache 块里面的方法,会在第一次执行后,写入 redis,并且可以设定周期,这样第二次执行的时候会从 redis 里面取,起到缓存的效果
为此我是这样写的
class ActiveRecord::Base
def self.redis_cache seconds=300, &block
if !self.is_a?(Class)
mod = self.const_set(:TopMethods, Module.new)
mod.module_eval &block
include mod
else
self.superclass.class_eval &block
end
require 'sourcify'
s = block.to_source(:strip_enclosure => true)
s.split(/\n/).select{|f| f.include?('def')}.each do |s|
m_name = s.gsub('def', '').split('(')[0].strip
self.class_eval <<-CODE
def #{m_name}(*args)
key = __method__.to_s + args.join('-')
key += ('-' + self.id.to_s) if !self.is_a?(Class)
puts key
results = Api::RedisClient.get(key)
if results
puts 'from redis'
results
else
results = Api::RedisClient.set(key, super)
Api::RedisClient.set_expire(key, "#{seconds}".to_i)
super
end
end
CODE
end
end
end
思路是这样的,拿到 block 之后,找到 self 的 superclass,把方法写在里面,然后再打开 self,再写一遍方法,这样就能用 super 往上面找,我用的解析代码块的 gem 'sourcify' http://numbers.brighterplanet.com/2010/12/17/replacing-parsetree-in-ruby-1-9/不是很稳定,复杂的方法经常解析报错,有什么更好的实现思路吗。