3

在同一应用程序中使用 identity_cache (v 0.0.4) 和 delayed_job (v 3.0.3) 时,我收到错误“#<Hash:0x007f9836dfdab0> 的未定义方法 `tag='”。

我跟踪了堆栈跟踪,发现delayed_job 覆盖了ActiveRecord::Base#encode_with。在delayed_job 版本中,它调用

coder.tag = ['!ruby/ActiveRecord', self.class.name].join(':')

似乎 ActiveRecord::Base 期望 coder 是一个 Hash,而 delay_job 假设它是一个 Psych::Coder,它确实有一个 tag= 方法。

最后,identity_cache 确实调用了 encode_with,并传递了一个 Hash。因此错误。

我正在使用 ruby​​ 1.9.3p429,它包含 psych 作为标准库。我没有在任何地方指定 yaml 解析器引擎,当我检查时它总是返回 psych(有些人抱怨过类似的问题,但他们使用 syck 进行 yaml 解析)。

所以,我想问题是,我如何让 delay_job 与 identity_cache 配合得很好?

4

2 回答 2

0

pduey 的回答对我不起作用,因为自他回答以来 IdentityCache 代码发生了变化。

此问题的以下修复适用于 identity_cache 0.2.3:

# config/initializers/patch_identity_cache.rb:
ActiveRecord::Base.class_eval do
  def encode_with_override_override(coder)
    encode_with_without_override(coder)
    coder.tag = "!ruby/ActiveRecord:#{self.class.name}" unless coder.is_a? ::Hash
  end
  alias_method :encode_with, :encode_with_override_override
end
于 2015-04-24T10:10:52.053 回答
0

也许不是最优雅的解决方案,但下面的猴子补丁是一种解决方法。到目前为止,我还没有观察到任何错误。我把它放在 .../config/initializers/patch_identity_cache.rb 中:

module IdentityCache
  module ConfigurationDSL
    extend ActiveSupport::Concern

    module ClassMethods
      alias_method :original_build_normalized_has_many_cache, :build_normalized_has_many_cache
      def build_normalized_has_many_cache(association, options)
        original_build_normalized_has_many_cache(association, options)

        self.class_eval(ruby = <<-CODE, __FILE__, __LINE__)

          def #{options[:population_method_name]}
            @#{options[:ids_variable_name]} = #{options[:ids_name]}
            association_cache.delete(:#{association})
            @#{options[:records_variable_name]} = nil
          end

        CODE
      end
    end
  end
end
于 2013-12-05T17:40:42.323 回答