将多个错误类传递给ruby';美国的援救条款

将多个错误类传递给ruby';美国的援救条款,ruby,exception,rescue,Ruby,Exception,Rescue,我有一些代码需要在ruby中拯救多种类型的异常: begin a = rand if a > 0.5 raise FooException else raise BarException end rescue FooException, BarException puts "rescued!" end 我想做的是以某种方式存储我要在某个地方救援的异常类型列表,并将这些类型传递给救援子句: EXCEPTIONS = [FooException, BarE

我有一些代码需要在ruby中拯救多种类型的异常:

begin
  a = rand
  if a > 0.5
    raise FooException
  else
    raise BarException
  end
rescue FooException, BarException
  puts "rescued!"
end
我想做的是以某种方式存储我要在某个地方救援的异常类型列表,并将这些类型传递给救援子句:

EXCEPTIONS = [FooException, BarException]
然后:

rescue EXCEPTIONS

这是可能的吗?如果没有对
eval
的一些真正的黑客调用,这是可能的吗?我不抱希望,因为我在尝试上述操作时看到了
TypeError:rescue子句所需的类或模块

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

EXCEPTIONS = [FooException, BarException]

begin
  a = rand
  if a > 0.5
    raise FooException
  else
    raise BarException
  end
rescue *EXCEPTIONS
  puts "rescued!"
end
如果要像上面那样为数组使用常量(有
异常
),请注意不能在定义中定义它,而且如果在其他类中定义它,则必须使用其命名空间引用它。实际上,它不一定是常数


Splat操作员

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

rescue *EXCEPTIONS
意思与

rescue FooException, BarException
[BazException, FooException, BarException, BangExcepion]
您还可以在数组文字中使用它作为

[BazException, *EXCEPTIONS, BangExcepion]
这和

rescue FooException, BarException
[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]
对于其他类型的对象,它会返回自身

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

我刚刚遇到了这个问题,找到了另一个解决方案。如果您的
FooException
BarException
都将是自定义异常类,特别是如果它们都是主题相关的,您可以构造继承层次结构,使它们都从同一父类继承,然后只拯救父类

例如,我有三个异常:
FileNamesMissingError
InputFileMissingError
,和
OutputDirectoryError
,我想用一条语句来拯救它们。我创建了另一个名为
FileLoadError
的异常类,然后设置上述三个异常以从中继承。然后我只救了
FileLoadError

像这样:

class FileLoadError < StandardError
end

class FileNamesMissingError < FileLoadError
end

class InputFileMissingError < FileLoadError
end

class OutputDirectoryError < FileLoadError
end

[FileNamesMissingError,
 InputFileMissingError,
 OutputDirectoryError].each do |error| 
   begin  
     raise error
   rescue FileLoadError => e
     puts "Rescuing #{e.class}."
   end 
end
class FileLoadErrore
放入“拯救#{e.class}”
结束
结束
编辑/更新 我错过了原来问题的全部要点。
虽然被接受的答案是有效的,但在我看来,使用建议的技巧并不是一个好的做法。您可以始终使用所需(和通用)的包装功能
try/rescue


虽然@sawa给出的结果在技术上是正确的,但我认为它误用了Ruby的异常处理机制

正如作者的评论(通过指向一个旧的)所建议的,Ruby已经配备了一个干式异常处理机制:

puts 'starting up'
begin
  case rand(3)
  when 0
    ([] + '')
  when 1
    (foo)
  when 2
    (3 / 0)
  end
rescue TypeError, NameError => e
  puts "oops: #{e.message}"
rescue Exception => e
  puts "ouch, #{e}"
end
puts 'done'

通过使用这种技术,我们可以访问异常对象,它通常包含一些有价值的信息。

关于rescue*异常呢?这似乎在ruby 1.8.7中也能起作用。在这种情况下,在
异常
前面使用“*”字符的术语是什么?“我想再多学一点。”安迪,它叫splat。它通常具有将数组分解为逗号分隔的对象的效果。当在方法定义的参数接收位置使用时,它会以另一种方式使用:将参数放在一个数组中。它在各种场合都很有用。很高兴知道它适用于1.8.7。我相应地编辑了我的答案。请注意,如果要访问异常实例,请使用以下语法:
rescue INVALIDREQUESERROR,CardError=>e
(请参阅)此语法工作正常:
rescue*EXCEPTIONS=>e
,其中
EXCEPTIONS
是异常类名的数组。-1这是OP在问题中使用的语法。他想将该列表提取到一个更易于维护的位置,我想这是因为相同的异常类型列表必须在多个位置重复,并且对列表的更新很容易出错。@segfult只有在阅读了您的评论后,我才最终理解了OP的问题。。