2013-05-09 4 views
0

Я написал программу, которая использует внешний рубиновый камень. Поскольку я делаю много разных действий с этим, я хочу, чтобы иметь возможность спасти и обрабатывать исключения по всем направлениям, вместо того, чтобы внедрять их каждый раз, когда я вызываю метод.Ловля исключений при использовании внешнего драгоценного камня

Каков наилучший способ для этого?
Должен ли я писать свой собственный метод, который просто вызывает внешний камень, а также спасает исключения? Или есть другой способ сделать что-то вроде «Всякий раз, когда исключение такого типа появляется в любом месте программы, обрабатывайте его таким образом»?

Я знаю, что если бы я написал внешний код драгоценного камня, я мог бы добавить обработку ошибок, как это, но это невозможно.

ответ

1

Основным ответом на это, вероятно, является объединение класса, с которым вы работаете; Ruby позволяет проявлять большую гибкость для этого, поскольку имеет метод method_missing и довольно динамичную среду класса. Вот пример (который может или не может быть смертельно испорчена, но демонстрирует принцип:

# A Foo class that throws a nasty exception somewhere. 
class Foo 
    class SpecialException < Exception; end 

    def bar 
    raise SpecialException.new("Barf!") 
    end 
end 

# This will rescue all exceptions and optionally call a callback instead 
# of raising. 
class RescueAllTheThings 
    def initialize(instance, callback=nil) 
    @instance = instance 
    @callback = callback 
    end 

    def method_missing(method, *args, &block) 
    if @instance.respond_to? method 
     begin 
     @instance.send(method, *args, &block) 
     rescue Exception => e 
     @callback.call(e) if @callback 
     end 
    else 
     super 
    end 
    end 
end 

# A normal non-wrapped Foo. Exceptions will propagate. 
raw_foo = Foo.new 

# We'll wrap it here with a rescue so that we don't exit when it raises. 
begin 
    raw_foo.bar 
rescue Foo::SpecialException 
    puts "Uncaught exception here! I would've exited without this local rescue!" 
end 

# Wrap the raw_foo instance with RescueAllTheThings, which will pass through 
# all method calls, but will rescue all exceptions and optionally call the 
# callback instead. Using lambda{} is a fancy way to create a temporary class 
# with a #call method that runs the block of code passed. This code is executed 
# in the context *here*, so local variables etc. are usable from wherever the 
# lambda is placed. 
safe_foo = RescueAllTheThings.new(raw_foo, lambda { |e| puts "Caught an exception: #{e.class}: #{e.message}" }) 

# No need to rescue anything, it's all handled! 
safe_foo.bar 

puts "Look ma, I didn't exit!" 

ли имеет смысл использовать очень общий вариант класса-оболочки, такие как класс RescueAllTheThings выше, или нечто большее особенно для того, что вы пытаетесь обернуть, будет зависеть от контекста и конкретных проблем, которые вы хотите решить.

Смежные вопросы