2017-01-04 31 views
0
begin 
    do_something 
rescue 
    Logger.write ... 

    ...error handling... 
end 

Проблема заключается в том, что это возможно, что код внутри спасения вызывает исключение. Для этого варианта использования я хочу его подавить.Что такое хороший способ подавить исключения внутри предложения rescue в Ruby?

Итак, как завернуть спасение в спасение, чтобы подавить Исключение?

+1

вы можете использовать другой 'начать rescue' блок внутри спасения. Или просто ничего не делайте в спасательном блоке. Я не знаю, в чем проблема. Если код вызывает исключение в блоке 'rescue', я хочу сказать вам: просто исправить ошибку :) – djothefou

ответ

3

Вы сказали, что сами

обернуть спасение в спасение

Исключение Inception

Там нет никакого особого пути, кроме упаковки блоков кода в begin rescue end блока:

begin 
    do_something 
rescue 
    begin 
    Logger.write ... 
    rescue 
    ...error handling... 
    end 
end 

... если вы не используете ActiveSupport: http://api.rubyonrails.org/classes/Kernel.html#method-i-suppress

suppress(Exception) do 
    # all exceptions will be suppressed 
end 

..но это не простая вещь, рубин, и я заметил, что вы не добавить рельсы тег на ваш вопрос. Хотя, вы можете реализовать suppress самостоятельно. Или, просто, вот принять это:

def suppress(*exception_classes) 
    yield 
rescue *exception_classes 
end 

Используйте, что в вашем спасении:

begin 
    do_something 
rescue 
    Logger.write ... 

    suppress Exception do 
    ...error handling... 
    end 
end 

В простом старом Руби это должен быть спасает весь путь вниз (и действительно, suppress является только вложенной спасение), но позвольте мне сказать, что это плохая идея спасти все исключения, по сути, не будучи явным, о том, какое исключение вы спасаете, другими словами, не передавая аргумент класса исключения в rescue, вы неявно спасаете StandardError, который является суперклассом для большинства исключений (more info here). Это может привести к затруднению поиска ошибок.

begin  
rescue 
end 

..is так же, как:

begin 
rescue StandardError 
end 

Это гораздо лучше знать, что исключение вы спасая и быть четко об этом:

begin 
rescue SomeApiError => e 
    # do something when this specific exception occurs 
end 

С этим разобрался вас может использовать каскадную стратегию для спасения ваших исключений:

begin 
    # do the thing 
rescue SomeApiError => e 
    # specific rescue 
rescue SomeOtherError => e 
    # more broad error handling 
rescue 
    # catch all rescue 
end 

С учетом вышеизложенного будет выполняться только условие спасения, которое соответствует поднятому исключению, однако код в блоке спасения не будет спасен последующими спасениями, только код в блоке begin будет спасен.

Если вы хотите иметь блок кода, который всегда работает даже в случае исключения, используйте ключевое слово ensure:

begin 
    # code 
rescue => e 
    # rescue code 
ensure 
    # this block will always run exception or not 
end 
+0

' rescue' не то же самое, что 'rescue Exception'. –

+0

@LukasBaliak благодарит вас за информативное понимание. – DiegoSalazar