Рубин десериализации YAML - PullRequest
4 голосов
/ 29 июля 2011

Я работаю с DelayedJob, и мне нужно переопределить метод, который я считал использованным, когда объект десериализован из YAML: self.yaml_new (определено в delayed/serialization/active_record)

У меня сложилось впечатление, что когда YAML десериализует некоторые данные, он вызовет метод yaml_new для класса типа этих данных

Метод DJ's yaml_new извлекает объект из базы данных, используя переданный идентификатор id

Я не могу добиться такого поведения с помощью своих собственных классов. Когда я устанавливаю self.yaml_new метод для класса и пытаюсь YAML.load для сериализованного экземпляра, кажется, что он не вызывает yaml_new, поэтому я, очевидно, ошибаюсь.

Для чего тогда этот метод?

Поиск yaml_new мало что дает (только документы API других людей, использующих его). Поэтому мне интересно, что именно этот метод.

Я подумал, что yaml_new - это какой-нибудь хук-метод, вызываемый при обнаружении объекта некоторого типа, если этот метод существует в классе. Но опять же я не могу заставить это работать. Ниже приведен образец:

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

Это именно то, что делает диджей, за исключением того, что я регистрирую действие.

YAML.load Contact.first.to_yaml
# => yaml_new!!!

Я действительно получаю зарегистрированный вывод !!

Так что же я делаю не так за пределами моего Rails-приложения? Есть ли другой способ заставить этот метод срабатывать ?? Я спрашиваю, потому что я пытаюсь проверить это в своем собственном геме, а метод yaml_new не срабатывает, поэтому мои тесты не проходят, и все же он действительно работает внутри Rails

1 Ответ

0 голосов
/ 29 июля 2011

Вам нужно добавить что-то вроде

yaml_as "tag:ruby.yaml.org,2002:B"

до определения метода self.yaml_new. Согласно комментариям в yaml / tag.rb, yaml_as:

Добавляет тег тег в класс, используемый при выгрузке или загрузке класса в ЯМЛ. Смотрите YAML :: tag_class для подробной информации о наборе текста и taguris.

...