代码阅读:为什么下面的代码是这样实现的?
我期待在代码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
,在Array上定义cache_key
有什么意义?
该方法的目的是为单个记录上的标准缓存之外的记录数组添加缓存,因此它在Array
中实现。很可能,作者试图通过将其包装在ActiveRecord::Base
的class_eval中来污染类别ruby Array
。这种方法不会防止这种污染,但它会增加所需的方法。
使用class_eval
而不是仅仅重新打开类的唯一原因是在类不存在的情况下快速失败。这是不可能的,因为你已经显示了代码,因为ActiveRecord是必需的。我猜想作者只是有一个奇怪的风格偏好。
我希望这只会改变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
不存在,这会提高。
检查ActiveRecord的好处,虽然有更直接的方法来做同样的事情(例如'defined?')。 – PinnyM 2013-03-22 13:40:27
那么,这是否也适用于'ActiveRecord :: Relation'呢? – Geo 2013-03-11 18:11:30
@Tempus,这个代码是在2009年为Rails 2.3.x编写的,之前有'ActiveRecord :: Relation'(一个Rails 3.x概念)存在。不,它不适用于其他集合(除非它们是Array的子类)。 – PinnyM 2013-03-11 18:15:26