Autoloading Classes when Deserializing YAML Objects (or, What Is This YAML::Object?)

Rails will automatically load Ruby files from your /app, /lib, and other directories when you use the appropriately named constant. For example, if you use the name RailsExampleObject in your code, Rails will automatically look for a file called rails_example_object.rb and load it.

However, this autoloading of classes fails when deserializing objects from YAML. This can occur, for example, when reading an ActiveRecord object that has a serialize column. So, for example, say you read an ActiveRecord object from a database, and the object has a serialized column that contains an object of type RailsExampleObject. If the file rails_example_object.rb is not already loaded, then the YAML deserializer will give you a default object of type YAML::Object.

The way to solve this is to instruct the YAML deserializer to autoload classes the same way that Rails does. The following code seems to work for me to do this:

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

I wrote this code a long time ago, so I don’t know anymore why it works. But it does seem to work.

Comments 1