Aug 26

Ruby on Rails Class Serialize Problem

etienne @ 6:23 pm

I’ve been chasing my tail for the past day trying to track down a problem I was having in serializing a hash that contained two of my custom classes. I have two custom classes:

class Menu

end

class Permissions

end

I then have an ActiveRecord class that stores instances of these two classes in a hash which is then saved to my database.

class Role < ActiveRecord::Base

  serialize :credentials
  …
  self.credentials[:permissions] = Permissions.new(self)
  self.credentials[:menu] = Menu.new(self)
  …
end

After saving the record to the database I could inspect the field and all the YAML code was present and accounted for, the problem was that when I went to retrieve the serialized field, instead of getting back a hash with my two custom classes (i.e. Menu and Permissions) I was getting both objects of class YAML::Object.

After pulling my hair out for some time, I traced into the Rails code and saw that YAML::Load(string) was being called to unserialize the data. I then went to the YAML site and read more about the library which I admit I have limited knowledge about. I figured out that for some reason YAML was not finding my custom class definitions which meant it used YAML::Object. So now it was a matter of finding out how to tell YAML about my classes.

After doing more searching on the net I came across these articles which gave me the information I needed:

http://yaml4r.sourceforge.net/doc/page/type_families.htm
http://dev.rubyonrails.org/ticket/7537

I was able to add the following code to my environment.rb which will ensure any ActiveRecord derived classes will be correctly serialized. I also added two require statements to environment.rb to make sure my custom (non ActiveRecord derived) classes where also correctly serialized.

require ‘permissions’
require ‘menu’

YAML.add_domain_type("ActiveRecord,2007", "") do |type, val|
  klass = type.split(’:').last.constantize
  YAML.object_maker(klass, val)
end

class ActiveRecord::Base
  def to_yaml_type
    "!ActiveRecord,2007/#{self.class}"
  end
end

class ActiveRecord::Base
  def to_yaml_properties
    [’@attributes’]
  end
end

I restarted my server and everything worked !!!

 

14 Responses to “Ruby on Rails Class Serialize Problem”

  1. Ben Nevile says:

    Thanks, this helped me out today!

  2. etienne says:

    Hi Ben, I’m glad you found it useful thanks for letting me know.

  3. AkitaOnRails says:

    Hi, I wonder what the ‘2007′ stands for. Sorry for the noobie question. Could you clarify on that? And thanks for the findings, I am having the same problems here.

  4. etienne says:

    Hi AkitaOnRails,

    You can find out a bit more about the add_domain_type method in the YAML documentation at http://yaml4r.sourceforge.net/doc/, here is a quote from the docs:

    domain_and_date
    The domain and date (seperated by a comma) to assign the type under. An example for a personal type would be ‘your-company.com,2002-09-23′. The date can usually be just a year, representing the first day of year (’2002′ == ‘2002-01-01′). First day of the month can be shortened to just year and month (’2002-09′ == ‘2002-09-01′). See http://www.taguri.org/ for details on this convention.

    Hope this helps.

  5. Andrew Kuklewicz says:

    I ran into this awhile ago, and gave up quickly with a work around, then finally found your post and references to a real fix tonight - I am so happy I can’t even tell you.
    Thanks again

  6. etienne says:

    Hi Andrew,

    I’m glad it helped, thanks for the feedback it’s much appreciated.

  7. darius says:

    Helped me too! Thanks Etienne!

  8. etienne says:

    Hi Darius,

    Good to hear from you again, I appreciate the feedback.

  9. Ann says:

    This is really helpful. I was parallelizing a large ruby computation with skynet, and the skynet map and reduce steps each do ActiveRecord serialization and then unsuccessful deserialization (if you run your job with multiple mappers or reducers). Adding this patch to ActiveRecord fixes the deserialization problem! Many thanks!

  10. Feisty Piranha Project - BrightMix 2008 Summer Internship » Oh what a week! says:

    […] turns out that there were solutions to this problem (Like here, and a few other home-brewed solutions that I came up with) though they were not the solutions I […]

  11. Ben Greene says:

    Hey guys, another way to achieve this same goal is to require the model in the file that makes the serialize call. So:

    class StagingLot

  12. Andrew says:

    I was fighting with Rails for a few days to fix the same problem until i found your article. IOU a beer :)

  13. Eric says:

    Yet another person whose evening you’ve saved - thanks so much for posting this.

  14. etienne says:

    Hey Eric,

    I’ve been helped out of a pickle or two by others who have posted helpful articles so I’m happy to give back a little…

    Thanks for taking the time to say thanks, it’s much appreciated.

Leave a Reply