2

我有 10 个要执行的 Ruby 函数调用,每个调用都可能引发异常。我想以相同的方式处理每个异常并继续。有没有办法做到这一点而不将每一行包装在一个begin......块rescue中?end

[编辑]:用例是使用 Selenium Web 驱动程序填写表单的屏幕抓取工具/自动化工具。我不想费心检查选择元素中的选项是否存在,只要尽可能好地填写它们。为此,Selenium::WebDriver::Support::Select.select_by如果它抛出“无法找到值为 x 的选项”异常,我需要调用并继续。

4

5 回答 5

7

我发现这个答案也符合我的要求:

def action
    yield
    rescue
        ....
    ensure
        ....
end

action { call1 }
action { call2 }
action { call3 }
于 2012-10-24T08:26:48.000 回答
5

你的意思是这样的?

class Wtf
  def f1
    raise "f1"
  end
  def f2
    raise "f2"
  end
end

obj= Wtf.new

[:f1, :f2].each do |f|
  begin
    obj.send f
  rescue Exception=> e
    p e
  end
end

编辑:在示例中添加了更多代码

于 2012-10-23T11:57:38.260 回答
2

我喜欢 qwned 的 #send 方法,但对于并非所有方法都将按顺序调用的情况,它并不理想。

延续非常适合这种事情:

require 'continuation'

class Continuer

  # Define five methods for testing
  (1..5).each { |i| define_method("method#{i}") { puts "method#{i} called" } }

  def do_these_things
    cc = nil
    callcc { |c| cc = c; method1; }
    callcc { |c| cc = c; method2; raise }
    # Do other things right here, maybe...
    callcc { |c| cc = c; method3; raise }
    callcc { |c| cc = c; method4; }
    callcc { |c| cc = c; method5; }
  rescue
    puts 'Caught exception.  Continuing.'
    cc.call
  end

end

Continuer.new.do_these_things

这通过在执行每个容易失败的方法时在“cc”变量中记录延续来工作。然后,救援语句只是在该继续处恢复。这有点像带有动态标签的 goto 语句。

于 2012-10-23T13:53:50.167 回答
0

你可以做:

begin
  do_something
  do_something_else
  do_do_do
rescue Exception1 => e
  # error handling
rescue Exception2 => e
  # error handling

如果 do_something 抛出异常,则不会调用其他调用。而且我认为比做很多begin.. rescue块更好。只需处理不同的异常。

于 2012-10-23T12:13:14.233 回答
0
def f1; raise "X"; end
def f2; raise "Y"; end
#...
funcList = [:f1,:f2,...]
funcList.each{|f|
     begin
       send(f)
     rescue Exception => e
        #handle
     end
 }
于 2012-10-23T13:43:00.150 回答