【问题标题】:Code reading: why is the following code implemented like this?代码阅读:为什么下面的代码是这样实现的?
【发布时间】:2013-02-27 00:18:05
【问题描述】:

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

【问题讨论】:

    标签: ruby-on-rails ruby caching activerecord


    【解决方案1】:

    该方法的目的是除了对单个记录进行标准缓存之外,还为记录数组添加缓存,因此它是在Array 中实现的。最有可能的是,作者试图不污染 ruby​​ Array 类,方法是将它包装在 ActiveRecord::Base 的 class_eval 中。这种方法不会防止这种污染,但会添加所需的cache_key 方法。

    【讨论】:

    • 那么,这是否也适用于ActiveRecord::Relation
    • @Tempus,此代码是在 ActiveRecord::Relation(Rails 3.x 概念)存在之前于 2009 年为 Rails 2.3.x 编写的。不,它不适用于其他集合(除非它们是 Array 的子类)。
    【解决方案2】:

    使用class_eval 而不是仅仅重新打开类的唯一原因是在类不存在的情况下快速失败。这在您显示的代码中是不可能的,因为需要 ActiveRecord。我猜作者只是有一种奇怪的风格偏好。

    【讨论】:

      【解决方案3】:

      我希望这只会在ActiveRecord 的上下文中改变Array

      所以我创建了一个小测试程序来验证:

      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?)。
      猜你喜欢
      • 2013-01-05
      • 2020-07-30
      • 2015-03-12
      • 2016-11-25
      • 2019-02-27
      • 1970-01-01
      • 2015-07-07
      • 1970-01-01
      • 2017-07-13
      相关资源
      最近更新 更多