我正在使用 DelayedJob,我需要覆盖一个我认为在从 YAML 反序列化对象时使用的方法:self.yaml_new
(定义在在 delayed/serialization/active_record
)
我的印象是,当YAML反序列化一些数据时,它会调用该数据类型的类的yaml_new
方法
DJ 的 yaml_new
方法使用传入的 id 从数据库中获取对象
我无法通过自己的类(class)实现此行为。当我在类上设置 self.yaml_new
方法并尝试在序列化实例上 YAML.load
时,它似乎没有调用 yaml_new
所以我肯定是弄错了。
那么这个方法有什么用呢?
搜索 yaml_new
不会产生太多(只是其他人使用它的 API 文档)。所以我想知道这个方法到底是什么。
我认为 yaml_new
将是某个钩子(Hook)方法,当发现某个类型的对象时调用该方法(如果类中存在该方法)。但我又无法让它发挥作用。下面是一个示例:
class B
def self.yaml_new(klass, tag, val)
puts "I'm in yaml new!"
end
end
b = B.new
YAML.load b.to_yaml # expected "I'm in yaml new!" got nothing
更新
所以在我的 Rails 应用程序中试玩之后,yaml_new
确实实际上是从 YAML.load
调用的。我有一个这样的文件:
module ActiveRecord
class Base
def self.yaml_new(klass, tag, val)
puts "\n\n yaml_new!!!\n\n"
klass.find(val['attributes']['id'])
rescue ActiveRecord::RecordNotFound
raise Delayed::DeserializationError
end
def to_yaml_properties
['@attributes', '@database'] # add in database attribute for serialization
end
end
end
这正是 DJ 所做的,只是我正在记录操作。
YAML.load Contact.first.to_yaml
# => yaml_new!!!
我实际上得到了记录的输出!
那么我在 Rails 应用程序之外做错了什么?还有其他方法可以触发此方法吗?我问是因为我试图在我自己的 gem 中测试它并且 yaml_new
方法没有触发,所以我的测试失败了,但它确实在 Rails 中工作
最佳答案
你需要添加类似的东西
yaml_as "tag:ruby.yaml.org,2002:B"
在 self.yaml_new
方法的定义之前。根据yaml/tag.rb中的注释,yaml_as:
Adds a taguri tag to a class, used when dumping or loading the class in YAML. See YAML::tag_class for detailed information on typing and taguris.
关于Ruby 反序列化 YAML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6877712/