- Рельсы: 3.0.3
- Рубин: 1.9.2
Попытка десериализации очень простого объекта с использованием YAML.load
или Marshal.load
приводит к повреждению объекта, поскольку принадлежащий ему класс не требуется в процессе десериализации.
Пример:
# app/models/my_model.rb
class MyModel
attr_accessor :id
end
# test/unit/serializing_test.rb
require 'test_helper'
class SerializingTest < Test::Unit::TestCase
def test_yaml_serialize_structure
my_model = MyModel.new
my_model.id = 'my model'
File.open( "#{Rails.root}/tmp/object.yml" , 'w' ) do |f|
YAML::dump(my_model, f)
end
end
def test_yaml_deserialize_structure
object = YAML.load_file "#{Rails.root}/tmp/object.yml"
assert( object.instance_of? MyModel )
assert_equal( 'my model', object.id )
end
end
С помощью этого кода мы можем запустить этот сеанс консоли оболочки без ошибок:
$ ruby -Itest test/unit/serializing_test.rb -n test_yaml_serialize_structure
$ ruby -Itest test/unit/serializing_test.rb -n test_yaml_deserialize_structure
Но если я запускаю вызовы десериализации из консоли Rails, объект не десериализуется должным образом, поскольку класс никогда не требуется:
$ rails c
ruby-1.9.2-p0 > object = YAML.load_file "#{Rails.root}/tmp/object.yml"
=> #<Syck::Object:0x0000010322ea30 @class="MyModel", @ivars={"id"=>"my model"}>
Я знаю, что единственная проблема заключается в том, что класс не требуется, потому что, если я запрашиваю его вручную, все работает:
ruby-1.9.2-p0 > require "#{Rails.root}/app/models/my_model"
=> ["MyModel"]
ruby-1.9.2-p0 > object = YAML.load_file "#{Rails.root}/tmp/object.yml"
=> #<MyModel:0x0000010320c8e0 @id="my model">
Я представил только примеры YAML, но с маршалом все точно так же.
Также скажите, что хотя я воспроизводил проблему в консоли Rails , изначально эта проблема сводила меня с ума при обычном запросе к моему приложению.
Итак, вопрос в следующем: Как я могу десериализовать объекты в Rails без необходимости вручную запрашивать все мои классы?
Спасибо
е.