开发者

Ruby deserializing YAML

开发者 https://www.devze.com 2023-03-24 09:45 出处:网络
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)

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消