我正在查看group_cache_key方法的代码,我以前从未见过这种写法:
require 'activerecord'
require 'activesupport'
require 'digest/md5'
ActiveRecord::Base.class_eval {
Array.class_eval {
def cache_key
if self.empty?
'empty/' + self.object_id.to_s
else
ids_hash = Digest::MD5.hexdigest(self.collect{|item| item.id }.to_s)
update_timestamp = max {|a,b| a.updated_at <=> b.updated_at }.updated_at.to_i.to_s
create_timestamp = max {|a,b| a.created_at <=> b.created_at }.created_at.to_i.to_s
self.first.class.to_s.tableize+'/'+length.to_s+'-'+ids_hash+'-'+create_timestamp+'-'+update_timestamp
end
end
}
}
为什么这个方法实现了?在class_eval
中设置class_eval
并在数组上定义cache_key
有什么意义?
答案 0 :(得分:3)
该方法的目的是为单个记录上的标准缓存添加记录数组的缓存,因此它在Array
内实现。最有可能的是,作者试图通过将它包装在Array
的class_eval中来不污染ruby ActiveRecord::Base
类。这种方法不会阻止这种污染,但它会添加所需的cache_key
方法。
答案 1 :(得分:1)
使用class_eval
而不是仅重新打开类的唯一原因是在类不存在的情况下快速失败。这在您显示的代码中是不可能的,因为需要ActiveRecord。我猜想作者只是有一种奇怪的风格偏好。
答案 2 :(得分:1)
我希望这只会在Array
的上下文中更改ActiveRecord
。
所以我创建了一个小测试程序来验证:
class Test
class Array
def initialize(bla)
@array = bla
end
end
def self.get_array_of(something)
Array.new([something])
end
end
Test.class_eval {
Array.class_eval {
def to_s
"BLAAAAAAAA"
end
}
}
puts ["a", "b", "c"].to_s
puts Test.get_array_of("b").to_s
遗憾的是,此计划的输出表明只有全局Array
受到影响,Test::Array
仅具有默认的to_s
功能。长号。
因此,我可以考虑这样做的唯一原因是因为如果ActiveRecord
不存在,这将会提高。