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