以DRY方式将多个错误类传递给ruby的救援条款

我有一些代码需要在ruby中拯救多种types的exception:

begin a = rand if a > 0.5 raise FooException else raise BarException end rescue FooException, BarException puts "rescued!" end 

我想要做的是以某种方式存储我想要救援的exceptiontypes列表,并将这些types传递给rescue子句:

 EXCEPTIONS = [FooException, BarException] 

接着:

 rescue EXCEPTIONS 

这甚至是可能的,是否有可能没有一些真正的黑客调用eval ? 我没有希望,因为我看到TypeError: class or module required for rescue clause当我尝试上述的TypeError: class or module required for rescue clause

您可以使用splat运算符*的数组。

 EXCEPTIONS = [FooException, BarException] begin a = rand if a > 0.5 raise FooException else raise BarException end rescue *EXCEPTIONS puts "rescued!" end 

如果你要为上面的数组使用一个常量(使用EXCEPTIONS ),请注意,你不能在定义中定义它,而且如果你在其他类中定义它,你必须用它的名字空间来引用它。 事实上,它不一定是一个常数。


摔跤运营商

splat操作符* “解包”一个数组在其位置,以便

 rescue *EXCEPTIONS 

的意思是一样的

 rescue FooException, BarException 

你也可以在数组中使用它

 [BazException, *EXCEPTIONS, BangExcepion] 

这是一样的

 [BazException, FooException, BarException, BangExcepion] 

或者在争论的位置

 method(BazException, *EXCEPTIONS, BangExcepion) 

意思是

 method(BazException, FooException, BarException, BangExcepion) 

[]扩大到虚空:

 [a, *[], b] # => [a, b] 

ruby1.8和ruby1.9之间的一个区别是nil

 [a, *nil, b] # => [a, b] (ruby 1.9) [a, *nil, b] # => [a, nil, b] (ruby 1.8) 

要小心处理to_a对象,因为在这种情况下to_a将被应用:

 [a, *{k: :v}, b] # => [a, [:k, :v], b] 

与其他types的对象,它返回自己。

 [1, *2, 3] # => [1, 2, 3] 

我刚刚遇到这个问题,并find了一个替代解决scheme。 在这种情况下,你的FooExceptionBarException都将是自定义的exception类,特别是如果它们都是关联的,你可以构造你的inheritance层次结构,使得它们将从同一个父类inheritance,然后只拯救父类。

例如,我有三个例外: FileNamesMissingErrorInputFileMissingErrorOutputDirectoryError ,我想用一个语句来拯救。 我做了另一个名为FileLoadErrorexception类,然后设置上述三个exceptioninheritance它。 然后我只救了FileLoadError