One of my favourite things about Ruby is that they release new versions on Christmas day! This year 2.1 came out with a range of neat features, but the most exciting from our point of view is the new cause method on Exception objects.
The [CODE]cause[/CODE] method tells you the original problem that was being handled when this exception was raised.
Knowing the cause of an exception is incredibly useful when you deliberately raise a more descriptive exception inside your error handler; as described by Avdi Grimm:
-- CODE language-ruby --
begin
# ...
rescue KeyError
raise MyLib::Error, "Bad key: #{key}. Valid keys are: #{valid_keys}"
end
Rails’ [CODE]ActionView[/CODE] does something similar when an exception occurs in a view helper. The original exception is wrapped in an [CODE]ActionView::Template::Error[/CODE], and made available through the [CODE]original_exception[/CODE] method so that you can tell quickly where the problem was.
[CODE]Exception#cause[/CODE] is also very useful for diagnosing bugs in your exception handlers. If your exception handler has a bug, a second exception will be raised to tell you about the bug. For example:
-- CODE language-ruby --
begin
# ...
rescue
# Bug which throws a NoMethodError in your exception handler
nil.some_method
end
Before [CODE]Exception#cause[/CODE] this second exception would completely hide the first, making it almost impossible to figure out why your program crashed originally.
The Bugsnag user interface has supported showing exception causes since day one. This was predominantly to support languages that already had a similar feature, like Java’s [CODE]getCause()[/CODE] and Rails’ [CODE]ActionView::Template::Error[/CODE].
Now that Ruby 2.1 provides a standard mechanism for showing the causes of exceptions, we’ve updated our ruby notifier to automatically collect and display these causes. You can get the latest version with [CODE]bundle update bugsnag[/CODE].
If you’re not yet using Ruby 2.1 you can get all the benefits of [CODE]Exception#cause[/CODE] by installing the cause gem. It provides a backport of the cause method to ruby 1.8.7 and above so that if your error handlers ever crash, or you want to make use of descriptive error classes, you can still debug the original problem effectively.