begin
do_something
rescue
Logger.write ...
...error handling...
end
问题在于,救援中的代码可能引发异常。对于此用例,我想取消它。
那么,如何在救援中包装救援以抑制Exception?
最佳答案
你自己说的
异常(exception)开始
除了将代码块包装在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)的父类(super class)。这可能导致难以发现错误。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