Serialize / Deserialize nested objects in ActiveRecord

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.

DeliciousTwitterFacebookLinkedInRedditSlashdotTechnorati FavoritesDiggShare
This entry was posted in Ruby, RubyOnRails. Bookmark the permalink.

2 Responses to Serialize / Deserialize nested objects in ActiveRecord


  1. I’ve had similiar problem which I’ve solved with a nasty hack which I don’t like.

    Rails ActiveRecord serialize method doesn’t work in test environment.

    Maybe You could take a look and see if there is a better solution for that.

  2. Alex says:


    Hi,

    I’ve got same issue, when loading serrialized object from DB some of the nested objects do not load. Unfortunately I cannot see the rails solution for the ticket in lighthouseapp as it is private, can you help by making it public ? or maybe if you have membership you can post the solution from ticket content here ?

    Thanks a lot.

Leave a Reply

Your email address will not be published. Required fields are marked *

*


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">