Ruby exceptions and YAML

I’m confused by how YAML seems to not work with ruby exceptions. I
tried searching in vain, thus this quick post.

I would like to serialize and deserialize exception objects, but when I
deserialize a serialized exception, it does not appear to be able to
access the original message, even thought the YAML output seems to have
it. I would think that for any ruby object ‘obj’, the following should
hold:

obj == YAML::load(YAML::dump(obj))

but this seems to not be the case. Here is a short test script
illustrating the issue:

require ‘cgi’
require ‘yaml’

begin
raise “Ain’t got no mojo”
rescue => ex
if YAML::load(YAML::dump(ex)) != ex
puts “NOT EQUAL”
end

    puts "class=#{ex.class} message=#{ex.message}"
    puts ex.message

    dumped = YAML::dump(ex)
    puts dumped

    loaded = YAML::load(dumped)
    puts "class=#{loaded.class} message=#{loaded.message}"

    dumped_2 = YAML::dump(loaded)
    puts dumped_2

    loaded_2 = YAML::load(dumped_2)
    puts "class=#{loaded_2.class} message=#{loaded_2.message}"

end

and here is a run:

% ruby --version
ruby 1.8.6 (2008-03-03 patchlevel 114) [x86_64-linux]
% ruby test_exception_dump.rb
NOT EQUAL
class=RuntimeError message=Ain’t got no mojo
Ain’t got no mojo
— !ruby/exception:RuntimeError
message: Ain’t got no mojo
class=RuntimeError message=RuntimeError
— !ruby/exception:RuntimeError
message: RuntimeError
mesg: Ain’t got no mojo
class=RuntimeError message=RuntimeError

Have I misunderstood something here, or is there something fundamentally
wrong with ruby YAML?

Bill

On Thursday 01 May 2008, Bill Lear wrote:

 I would think that for any ruby object ‘obj’, the following should
hold:

obj == YAML::load(YAML::dump(obj))

but this seems to not be the case.

It depends on the == methods for the class in question. If you try the
same
using, for example, an array, you’ll find that the comparison returns
true.
This happens because Array redefines the == method defined in class
Object,
which returns true only if the two operands are the same object. Class
Exception, instead, doesn’t redefine it, and so the comparison between
two
exceptions will always return false, unless they’re the same object.
This
means that this will return false:

RuntimeError.new(‘msg’) == RuntimeError.new(‘msg’)

Since YAML.load creates a new object basing on the contents of its
argument,
the returned Exception is different (according to ==) from the original.

I hope this helps

Stefano

Stefano C. wrote:

On Thursday 01 May 2008, Bill Lear wrote:

I would think that for any ruby object ‘obj’, the following should
hold:

obj == YAML::load(YAML::dump(obj))

but this seems to not be the case.

It depends on the == methods for the class in question. If you try the
same
using, for example, an array, you’ll find that the comparison returns
true.
This happens because Array redefines the == method defined in class
Object,
which returns true only if the two operands are the same object. Class
Exception, instead, doesn’t redefine it, and so the comparison between
two
exceptions will always return false, unless they’re the same object.
This
means that this will return false:

RuntimeError.new(‘msg’) == RuntimeError.new(‘msg’)

Since YAML.load creates a new object basing on the contents of its
argument,
the returned Exception is different (according to ==) from the original.

I hope this helps

Stefano

Thanks for the clarification, but that’s really not the main issue,
although it is curious to me that ‘==’ means “the same object” rather
than logically identical, but if that is a ruby-esque idiosyncrasy, then
I can live with it.

The main issue is why the “message” member of the exception is clearly
in the YAML dumped output, but is not loaded and available to the loaded
instance. That, to me, is a far more serious problem. Again, if I do
this:

yamilized_exception = YAML::load(YAML::dump(original_exception))

then yamlized_exception.message will be (in my case) “RuntimeError”,
whereas original_exception.essage will be “Ain’t got no mojo”, even
though the YAML::dump(original_exception) is:

— !ruby/exception:RuntimeError
message: Ain’t got no mojo

Bill

Bill