Gerando novamente uma exceção como outra em Ruby

É uma boa ideia relançar exceções de bibliotecas de terceiros como se fossem suas, para não vazar detalhes de implementação em toda a sua base de código. Por exemplo, prefiro lidar com minha própria Facebook::Page::Inaccessibleexceção do que FbGraph::NotFoundfora do meu adaptador do Facebook.

Se o seu adaptador tem muitos lugares que podem vazar exceções, no entanto, reaumentá-los em todos os lugares envelhece muito rápido. Podemos aproveitar o novo prependmétodo em Ruby 2.0 para tornar as coisas realmente fáceis e bonitas:

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