less than 1 minute read

We ran into an interesting gotcha on our project the other day. We use serialize on ActiveRecord to save ruby objects to the database. This is described in Jay Fields Thoughts: Rails: ActiveRecord Serialize method.

Serialize uses YAML.dump and YAML.load to serialize/deserialize objects to strings. These methods only deal with the data of an object, not the methods. The objects we serialized used metaprogramming to dynamically define methods. When they were loaded from the database, they no longer had the new methods.

Here is a contrived example. The Foo class creates a foo method in the initialize:

class Foo
  def initialize
    class << self
      define_method :foo, lambda { 10 }
    end
  end
end
>> Foo.new.foo
=> 10

A dump of the Foo class has no knowledge of this foo method:

>> require 'yaml'
>> YAML.dump(Foo.new)
=> "--- !ruby/object:Foo {}\n\n"

Therefore, the loaded version of Foo will not have the foo method:

>>YAML.load(YAML.dump(Foo.new)).foo
NoMethodError: undefined method `foo' for #
        from (irb):16

In our case, we changed our code to store only the data from the domain object in the database (in columns). We recreate the domain object from these columns when we need it.

Updated: