代码阅读:为什么以下代码实现如下?

时间:2013-03-11 17:43:00

标签: ruby-on-rails ruby caching activerecord

我正在查看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有什么意义?

3 个答案:

答案 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不存在,这将会提高。