【问题标题】:What is a good way to suppress exceptions inside the rescue clause in Ruby?在 Ruby 的救援子句中抑制异常的好方法是什么?
【发布时间】:2017-05-19 08:54:53
【问题描述】:
begin
  do_something
rescue
  Logger.write ...

  ...error handling...
end

问题在于 rescue 中的代码 可能引发异常。对于这个用例,我想压制它。

那么,如何将救援包裹在救援中以抑制异常?

【问题讨论】:

  • 你可以在救援中使用另一个 begin rescue 块。或者只是在救援区什么都不做。我不确定你的问题是什么。如果代码在您的 rescue 块上引发异常,我想说的是:只需修复错误 :)

标签: ruby exception error-handling rescue


【解决方案1】:

你自己说的

将救援包裹在救援中

异常启动

除了将代码块包装在 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

..但这不是一个普通的 Ruby,我注意到你没有在你的问题中添加 rails 标签。不过,您可以自己实现suppress。或者,就拿这个吧:

def suppress(*exception_classes)
  yield
rescue *exception_classes
end

在你的救援中使用它:

begin
  do_something
rescue
  Logger.write ...

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

在普通的旧 Ruby 中,它必须一直是救援(实际上,suppress 只是一个嵌套救援),但我只想说救援所有异常是一个坏主意,本质上,不被明确说明您要抢救的异常,换句话说,通过不将异常类参数传递给rescue,您隐式抢救了StandardError,这是大多数异常的超类(more info here)。这可能会导致难以发现错误。

begin    
rescue
end

..等同于:

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

【讨论】:

  • rescuerescue Exception 不同。
猜你喜欢
  • 1970-01-01
  • 2021-12-19
  • 2012-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-31
  • 1970-01-01
  • 2014-02-27
相关资源
最近更新 更多