3

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の中に aを持ち、 Arrayclass_evalで定義する意味は何ですか?cache_key

4

3 に答える 3

3

このメソッドの目的は、個々のレコードに対する標準のキャッシングに加えて、レコードの配列に対するキャッシングを追加することです。そのため、 内に実装されArrayました。おそらく、作成者は rubyArray​​ クラスを class_eval の中にラップすることで汚染しないようにしようとしていたのでしょうActiveRecord::Base。このアプローチは、この汚染を防ぐことはできませんが、cache_key望まれていた方法を追加します。

于 2013-03-11T18:10:01.867 に答える
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存在しない場合に発生するからです。

于 2013-03-17T15:50:24.953 に答える
1

クラスを再開する代わりに使用する唯一の理由class_evalは、クラスが存在しないシナリオですぐに失敗することです。ActiveRecord が必要であるため、これはあなたが示したコードでは不可能です。著者は奇妙な文体の好みを持っていたと思います。

于 2013-03-17T03:12:50.610 に答える