我想立即为find_by_id
编写自定义ActiveRecord缓存。
为此,我想覆盖find方法,当只给出一个int时使用我的缓存,否则使用默认实现。
class X < ActiveRecord::Base
def self.find(*args)
return XCache[args[0]] if args.size == 1 && args[0].is_a?(Numeric)
return super.find(*args)
end
end
除了我与X的其他实例之间存在关联的情况外,一切都有效,例如:亲子关系:
has_many :x_children
has_many :children, :class_name => "X", :through => :x_children
当我致电X.find(1).children
时,我收到Enumerator
而不是Array
,这是不好的,因为我有时使用[]运算符。
即使使用枚举器也不能正常工作 - 在迭代我得到的最后一个条目时:
NoMethodError: undefined method `call' for :all:Symbol
任何帮助都将受到高度赞赏
进一步解释:
XCache只是一个缓存ActiveRecord实例的类。 一个简单的实现可以
class XCache
@@cache = {}
def self.[id]
return @@cache[id] ||= X.find(id)
end
end
(更高级的实现可以包括到期时间,Memcached等,更通用的解决方案可以支持多个模型类。)
我不认为我的问题与缓存实现有关(但我可能错了)
答案 0 :(得分:1)
正如您所见,这里有很多隐藏的复杂性。您可以查看cache-money宝石,这些人花了很多精力搞清楚。
要查看的其他宝石:simple_cacheable
答案 1 :(得分:0)
不确定它是否有帮助,但......这就是内部的发现:
def find(*args)
options = args.extract_options!
validate_find_options(options)
set_readonly_option!(options)
case args.first
when :first then find_initial(options)
when :last then find_last(options)
when :all then find_every(options)
else find_from_ids(args, options)
end
end
您不需要重载“find”,而是“find_from_ids”
这将让你独自留下使用find的所有其他方式,并且只针对你自己的用法。给予枚举器是find(:all)返回的...它可能有助于你的情况(或者可能不会)
其他可能性是...... Xcache只返回一个ActiveRecord,或者它有时可能返回一个集合......甚至是一个空集?
也许您可以尝试各种变体:
def self.find(*args)
if args.size == 1 && args[0].is_a?(Numeric)
rval = XCache[args[0]]
return rval if rval.present?
end
super.find(*args)
end