I'm currently experimenting with a framework in which exceptional conditions should be handled in a uniform manner -- but have more attributes than just a text message. The first thing I managed to come up with (thanks to a suggestion from apeiros on channel irc://irc.freenode.org/#ruby) was this:
class MyException < RuntimeError attr_reader :message unless (defined?(RuntimeError_initialize)) alias_method(:RuntimeError_initialize, :initialize) end def initialize(*args) RuntimeError_initialize(@message) end def message=(text) @message = text.to_s RuntimeError_initialize(@message) end end
apeiros subsequently offered this:
class MyException < RuntimeError; attr_accessor :message alias to_s message end
Which is pretty cool, although it doesn't address all of my needs. Nevertheless, it's another thing to add to the Ruby tricks-bag. The problem is that I don't know what else Ruby's Exception class might do with the text message it stores internally in something other than an instance variable named @message, as shown by this:
class E < RuntimeError def initialize(msg) super @message = 'something else' end end irb> x = E.new('this thing') => #<E: this thing> irb> raise x E: this thing from (irb):35 from :0
So however Exception is storing the message text internally, it apparently is not obviously accessible. And I'm a bit uncertain about substituting a separate mechanism; I'd rather use the one already in place. (Of course, since it's a FLOSS project, I can look at the source to see how it is done.)
Another for the tricks-bag is this one from StackOverflow, which allows you to change all keys of a hash to strings (which might wipe out any folded duplicates like {12=>7, "12"=>8}):
hash2 = hash1.inject({}) { |h, (k, v)| h[k.to_s] = v; h }
That was extremely useful since I was working with hashes with symbols for keys -- and JSON doesn't do symbols. (I subsequently reworked things to use string keys, which is less elegant but also less fragile in this scenario.)
Awesome.