From: Joel VanderWerf Date: 2004-11-07T12:38:13+09:00 Subject: exception extensions These are some extensions to Exception that I've found useful recently. Maybe someone else will too. The #details method outputs something like what ruby itself does when you see an exception in stderr. However, it returns a string, and you can control the threshold for removing informative lines with '...'. Also, the output is formatted more nicely, IMO. The #reraise_as method is useful when you want to catch something that's fairly opaque, like NameError, or NoMethodErr, and, using a more descriptive and app-specific exception class, raise it again, but with the same backtrace. Some example code is included. class Exception # More or less reproduces ruby's default exception reporting in # the returned string, except truncation can be controlled with # +maxlines+: +nil+ means no limit, an integer value means at # most maxlines/2 frames from each of the top and bottom # of the stack are reported. def details(maxlines=nil) bt = backtrace.dup bt0 = bt.shift if maxlines and maxlines < bt.size ml, r = maxlines.divmod(2) bt = bt[0...ml+r] + ["..."] + bt[-(ml==0 ? 1 : ml)..-1] end [ "#{bt0}: #{self.class}:", message, " from " + bt.join("\n from ") ].join("\n") end # Raise the exception, preserving the backtrace, but with as an # instance of class +cl+. The message is preserved by default, # but may be set to +msg+. def reraise_as(cl, msg = message) e = cl.new(msg) e.set_backtrace backtrace raise e end end class FooError < StandardError; end def foo bar(10) rescue StandardError => e puts e.details(5) puts "*"*40 e.reraise_as(FooError) end def bar(try) if try <= 0 raise " bar problem:\n can't find a bar\n anywhere around here" else bar(try-1) end end foo EXAMPLE OUTPUT: reraise.rb:43:in `bar': RuntimeError: bar problem: can't find a bar anywhere around here from reraise.rb:45:in `bar' from reraise.rb:45:in `bar' from reraise.rb:45:in `bar' from ... from reraise.rb:34:in `foo' from reraise.rb:49 **************************************** reraise.rb:43:in `bar': bar problem: (FooError) can't find a bar anywhere around here from reraise.rb:45:in `bar' from reraise.rb:45:in `bar' from reraise.rb:45:in `bar' from reraise.rb:45:in `bar' from reraise.rb:45:in `bar' from reraise.rb:45:in `bar' from reraise.rb:45:in `bar' from reraise.rb:45:in `bar' from reraise.rb:45:in `bar' from reraise.rb:45:in `bar' from reraise.rb:34:in `foo' from reraise.rb:49