Ruby deserializing YAML
I'm working with DelayedJob and I need to override a method that I thought was being used when an object is deserialized from YAML: self.yaml_new
(defined in in delayed/serialization/active_record
)
My impression was that when YAML deserialized some data, it would call the yaml_new
method on the class of the type of that data
DJ's yaml_new
method fetches the object from the database using the passed in id
I'm unable to achieve this behaviour with my own classes. When I set a self.yaml_new
method on a class and try to YAML.load
on a serialized instance, it doesn't seem to call yaml_new
so I must obviously be mistaken.
What then is this method for?
Searching for yaml_new
doesn't yield much (just API docs of other people using it). So I'm wondering what exactly this method is.
I figured yaml_new
would be some hook method called when an object is found of some type if that method existed on the class. But again I can't actually get this to work. Below is a sample:
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
updates
So after playing around in my Rails application, it appears that yaml_new
does actually get called from YAML.load
. I have a file in there like so:
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
Which is just what DJ does, except I'm logging the action.
YAML.load Contact.first.to_yaml
# => yaml_new!!!
I actually get the logged output!!
So what am I开发者_StackOverflow中文版 doing wrong outside of my Rails app?? Is there some other way of getting this method to trigger?? I ask because I'm trying to test this in my own gem and the yaml_new
method doesn't trigger, so my tests fail, and yet it actually does work inside Rails
You need to add something like
yaml_as "tag:ruby.yaml.org,2002:B"
before the definition of the self.yaml_new
method. According to the comments in 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.
精彩评论