views:

35

answers:

1

I have a db column which is a serialized Hash:

class Foo < ActiveRecord::Base
   serialize :bar
end

When I store a hash inside of bar that is a few levels deep, the deeper levels do not seem to properly deserialize when I need them. Objects one level deep get deserialzed just fine. However, objects 2 or more levels deep remain YAML classes.

I tried manually deserializing using YAML::load() but got an error saying the argument wasn't an instance of IO.

Does anyone know why the complete Ruby object doesn't deserialize?

EDIT: After further investigation, the problem seems to stem from the fact that I'm calling a virtual attribute from the serialized YAML.

class Foo < ActiveRecord::Base
   serialize :bar
end

class Bar < ActiveRecord::Base
    attr_accessor :enabled
end

@bars = @foo.bar[:bars]
@bars.each do |bar|
   puts bar.enabled
end

yields:

NoMethodError: undefined method `enabled' for #<YAML::Object:0xb6f11844>
    from (irb):12
    from (irb):11:in `each'
    from (irb):11
    from :0

Does this mean deserialization isn't "real", ie, the YAML object acts similar to the original object, but it's not an actual instance of that object?

+1  A: 

There's two things to keep in mind when serializing user-defined objects instead of "plain old Ruby" objects.

  • You need to have the user-defined classes loaded before the object can be properly de-serialized or the instances will be of a generic YAML::Object type. De-serializing does not auto-load classes.
  • Some objects may not properly serialize without some customization, though this is generally not the case.

Generally serializing instances of an ActiveRecord::Base object is a bad idea as these have an extraordinary amount of baggage that will need to be encoded in addition to your attribute. It is best to build a class that is derived directly from Object, which is the default behavior, or from a simple base class of some sort.

tadman