如何在 ruby 中引发多个异常

How to raise multiple exceptions in ruby

在 ruby 中,您可以像这样重新请求多个异常:

begin
   ...
rescue Exception1, Exception2
  ...
rescue Exception1
  ...
rescue Exception2
  ...
end

但我不知道如何引发多个异常:

1] pry(main)> ? raise

From: eval.c (C Method):
Owner: Kernel
Visibility: private
Signature: raise(*arg1)
Number of lines: 13

With no arguments, raises the exception in $! or raises
a RuntimeError if $! is nil.
With a single String argument, raises a
RuntimeError with the string as a message. Otherwise,
the first parameter should be the name of an Exception
class (or an object that returns an Exception object when sent
an exception message). The optional second parameter sets the
message associated with the exception, and the third parameter is an
array of callback information. Exceptions are caught by the
rescue clause of begin...end blocks.

   raise "Failed to create socket"
   raise ArgumentError, "No parameters", caller

或者我无法在 raise 文档中解决这个问题

这样做的目的是我有一个API调用,这个调用试图在API中创建一个对象。 然后 APi 可以 return 对象中的所有问题,来自 Activerecord Validators,所以我可以得到这样的想法,例如:

422 "The Item is not even","The Item needs too be bigger than 100" 422"The Item is not even" 200 好 "Item created" 500“我是茶壶

想法是捕获它并引发这样的异常

Begin
API CALL
rescue ItemnotEven,ItemnotBigger
do something 
retry if 
rescue ItemnotEven
retry if
rescue Connection error
Log cannot connect
end

我认为你不能引发多个异常,它会引发它找到的第一个异常,如果存在多个异常,它将被最里面的救援语句捕获,或者取决于你引发的异常类型和救援类型

在我所知道的任何语言中都不存在这样的概念。 您可以连续引发一个异常,但不能一次引发多个异常,即使在多个线程上引发"simultaneously",它仍然是在不同的控制流上引发一个异常。

当引发异常时,控制流将转到该异常。你有两个选择:做点什么,或者崩溃。没有第三种选择,也没有弹出单独的控制流,一直持续到这个异常被相应处理。

如果你想看到你在评论中所说的多次失败,那么你仍然会一次做一个,就像他们被提出来的那样。引发异常,您检查、记录、做任何事情、抑制它,然后查看下一个是否因其他原因引发。

如果你问如何引发多个未处理的异常,那真的没有意义。这类似于询问如何同时出现在两个地方。

异常不应用于验证。基本上你一般不应该遍历堆栈进行验证。

你基本上在做的是:

X是顶级的,什么都能搞定。 X 调用 Y。Y 调用 Z。Z 执行验证并在之后执行某些操作,如果验证失败则引发异常。

你应该做的是:

X 调用 Y。Y 调用 V 和 X。V 根据事物是否有效执行验证和 returns 结果。如果 V 说这个东西无效,Y 就不会打电话给 X。 Y 将无效或成功的结果传播给 X。X 在有效性上执行它本应使用 if/else 执行的操作,而不是 rescue.


但是假设您真的很想这样做。您应该使用 throw/catch 代替:

def validate_date(date)
  errors = []

  errors << 'Improper format' unless date.match?(/^\d{2}-\d{2}-\d{4}$/)
  errors << 'Invalid day' unless date.match?(/^[0-3]\d/)
  errors << 'Invalid month' unless date.match?(/-[12]\d-/)
  errors << 'Invalid year' unless date.match?(/[12][90]\d{2}$/)

  throw(:validation, errors) unless errors.empty?
end

def invoke_validation_and_do_stuff(date)
  validate_date(date)
  puts "I won't be called unless validation is successful for #{date}"
end

def meaningless_nesting(date)
  invoke_validation_and_do_stuff(date)
end

def more_meaningless_nesting(date)
  meaningless_nesting(date)
end

def top_level(date)
  validation_errors = catch(:validation) do
    more_meaningless_nesting(date)
    nil
  end

  if validation_errors
    puts validation_errors
  else
    puts 'Execution successful without errors'
  end
end


top_level '20-10-2012'
  # I won't be called unless validation is successful for 20-10-2012
  # Execution successful without errors

top_level '55-50-2012'
  # Invalid day
  # Invalid month