Last Updated: February 25, 2016
·
2.431K
· jgorset

Reraising an exception as another in Ruby

It's a good idea to reraise exceptions from third-party libraries as your own so you're not leaking implementation details all over your codebase. For example, I would rather deal with my own Facebook::Page::Inaccessible exception than FbGraph::NotFound outside of my Facebook adapter.

If your adapter has lots of places that could leak exceptions, however, reraising them everywhere gets old really fast. We can leverage the new prepend method in Ruby 2.0 to make things really easy and really pretty:

class Adapter
  extend Reraise

  reraise FbGraph::NotFound, as: Facebook::Page::Inaccessible, in: "query"

  def query
    raise FbGraph::NotFound, "This will be reraised as Facebook::Page::Inaccessible"
  end
end

Adapter.new.query # => Facebook::Page::Inaccessible: This will be reraised as Facebook::Page::Inaccessible
module Reraise

  # Rescue a given exception and raise another.
  #
  # old_exception - The Exception to rescue.
  # options       - A Hash of options:
  #                 :as - The Exception class to raise.
  #                 :in - A String or Array describing affected methods.
  def reraise old_exception, options
    new_exception = options.fetch :as
    methods       = options.fetch :in

    methods = [methods] unless methods.respond_to? :each

    proxy = Module.new do
      methods.each do |method|
        define_method method do |*args|
          begin
            super *args
          rescue old_exception => exception
            raise new_exception, exception
          end
        end
      end
    end

    class_eval do
      prepend proxy
    end
  end
end

1 Response
Add your response

I released this as a gem if you're into that kind of thing.

over 1 year ago ·