【转】Serialize / Deserialize nested objects in ActiveRecord

Monday, November 29, 2010

Using ActiveRecord’s
serialize
method you can save Ruby objects in a single field of your model. The
serialization is done through YAML. Today I tried to save a nested
object structure with this method. These are the classes:

class PhotoStyle
  attr_accessor :image

  def initialize
    @image = StyleElement.new
  end
end


class StyleElement
  attr_accessor :selector, :style

  def initialize
    @selector = '*'
    @style = {}
  end
end

The model which saves a PhotoStyle object:

class Photo < ActiveRecord::Base
  serialize :style, PhotoStyle
end

This first approach didn’t quite work out. Saving the model worked fine,
but when I loaded it only PhotoStyle got deserialized to the original
type. The nested StyleElement didn’t:

p = Photo.last
p.style
=> #<PhotoStyle:0xb70a906c @image=#<YAML::Object:0xb72079a4 @ivars={"selector"=>"#theimage", "style"=>{"border"=>"0", "box-shadow"=>"1px 3px 15px #555"}}, @class="StyleElement">}, @class="PhotoStyle">>

Note the YAML object assigned to the @image instance variable. I’m not
sure if that’s a bug in Rails3 or if that is by design. You can however
“fix” it by running this code snippet when your application starts up:

YAML::Syck::Resolver.class_eval do
  def transfer_with_autoload(type, val)
    match = type.match(/object:(\w+(?```\w+)*)/)
    match && match[1].constantize
    transfer_without_autoload(type, val)
  end
  alias_method_chain :transfer, :autoload
end

Save it e.g. in yaml_autoloader.rb in the config/initializers folder of
your app. Now all types will autoload:

#<PhotoStyle:0xb73dcb08 @image=#<StyleElement:0xb73dd058 @selector="#theimage", @style={"border"=>"0", "box-shadow"=>"1px 3px 15px #555"}>>

I found above code snippet here. Thanks!
Read more about ActiveRecord’s serialize method here: Simple user
preferences for your Rails
app
.

Update:
Still not sure if that’s a bug, but I submitted a lighthouse
ticket
.

Update 2:
Apparently this is not a bug in Rails, but a problem in my
code :-) Please see Aaron’s comment in above
ticket
.
http://blog.project-sierra.de/archives/1539

This entry was tagged Rails

comments powered by Disqus

© 2009-2013 lxneng.com. All rights reserved. Powered by Pyramid

go to Top