YAML, delayed_job: Псих против Сика. Как заставить pysch читать attr_accessors для объекта ruby
У меня проблемы с использованием delayed_job (3.0.3) с ruby 1.9.3. Ранее мы использовали ruby 1.8.7, который поставляется с парсером yaml syck, который считывает все атрибуты, которые установлены для объекта ruby (включая attr_accessors), но при обновлении до 1.9.3 парсер yaml был переключен на psy (который был повторно написано) и не учитывает никаких атрибутов, кроме тех, которые сохраняются в базе данных. Как мы можем сделать псих, чтобы принять во внимание attr_accessors. Я попытался переключиться на syck через:
YAML::ENGINE.yamler = 'syck'
Но все еще не работает.
У кого-нибудь есть решение этой проблемы?
2 ответа
Вышеупомянутый хак не работает, но все, что нам нужно, это переопределить методы encode_with и init_with ActiveRecord::Base, чтобы включить атрибуты доступа. Точнее, нам нужно установить хэш кодера с помощью att_accessors, и это позаботится о постоянстве переменных экземпляра.
Интересно почитать: https://gist.github.com/3011499
Десериализатор delayed_job НЕ вызывает init_with для загруженного объекта ActiveRecord.
Вот патч обезьяны для delayed_job, который вызывает init_with для результирующего объекта: https://gist.github.com/4158475
Например, с этим патчем обезьяны, если бы у меня была модель под названием Artwork с дополнительными атрибутами path и глубиной:
class Artwork < ActiveRecord::Base
def encode_with(coder)
super
coder['attributes']['path'] = self['path']
coder['attributes']['depth'] = self['depth']
end
def init_with(coder)
super
if coder['attributes'].has_key? 'path'
self['path'] = coder['attributes']['path']
end
if coder['attributes'].has_key? 'depth'
self['depth'] = coder['attributes']['depth']
end
self
end
end