2012-10-23 21 views
2

我有10個Ruby函數調用要執行,每個調用都可能引發異常。我想以相同的方式處理每個異常並繼續。有沒有辦法做到這一點,而不包裹每一行begin ... rescue ... end塊?在救援聲明中包裝每個命令

[編輯]:這是一個使用Selenium網絡驅動程序填寫表單的屏幕刮板/自動化工具。我不想麻煩檢查選擇元素中是否存在選項,只需儘可能好地填充它們即可。爲此,我需要調用Selenium::WebDriver::Support::Select.select_by並繼續,如果它拋出「無法找到值x選項」異常。

回答

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 

編輯:添加更多的代碼示例中

0

你可以這樣做:

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

如果do_something拋出和異常的其他電話將不會被調用。我認爲比做很多begin.. rescue塊更好。只是處理不同的例外。

+0

的發言都拋出同樣的異常,我希望他們都執行。所以不幸的是,這不是一個有效的答案:( – chiborg

+0

好的,但這取決於你的需要。你想要以不同的方式處理每個故障?爲什麼不把它們放在一個單一的救援塊?我猜你想知道「在那裏「拋出異常,所以你應該嘗試在每個函數(或內部)後改變一些」狀態「,然後在救援塊中查詢該狀態。 – mcortesi

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 
} 
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 

此效果是通過執行每個容易出現故障的方法時在「抄送」可變記錄的延續。救援聲明然後簡單地繼續下去。這有點像帶有動態標籤的goto語句。

6

我發現this answer也做什麼,我想:

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

action { call1 } 
action { call2 } 
action { call3 } 
+1

這看起來像是一個更一般的可重用解決方案! – nurettin