2011-10-04 53 views
7

的那一刻說我有:我可以訪問結合在一個異常的紅寶石

begin 
    2.times do 
    a = 1 
    1/0 
    end 

rescue 
    puts $! 
    debugger 
end  

在這個例子中,我想要得到的a值。如果abegin塊中初始化,那麼我可以在救援時訪問它。但是,在本例中,a是塊本地的。有沒有辦法在發生異常時獲得綁定?

+0

我不知道跨紅寶石雖然我記得RBX有一些巧妙的'Backtrace'對象可幫助你有效的解決方案的。你能否擴展你想要實現的目標? – riffraff

+0

@riffraff不知道如果我能更好地解釋它。我需要檢索一個(在這個例子中)的值。對於真實世界的場景,想象2X塊是一個迭代塊,每次從CSV文件中檢索一行。在某些情況下,(CSV文件的)行號203445發生異常。現在,我可以去那一行了。在CSV文件中檢查該特定行是否「OK」。或者我可以拯救並開始一個調試器會話。在此刻。我需要能夠看到綁定,在例外 – Vassilis

+0

謝謝,我所問的原因是,在類似的情況下,我有在do塊內的錯誤管理代碼,所以我有機會修復單個值並繼續前進,這似乎適合你的情況,儘管它沒有回答原來的問題,恐怕。我可以建議的唯一的事情是,如果錯誤不在本機代碼中,你可以重寫提升/失敗來存儲調用者的綁定,但它只是一個解決方案 – riffraff

回答

1

難道你不能只是把另一個begin,rescue塊內的do塊嗎?

+0

,我可以。這並不是說我無法檢查a的價值,或者我想要的任何其他價值。也許我的問題的標題是錯誤的。如果我可以重寫它,它會開始像「是否有可能訪問綁定...」,或者更好,「是否Ruby在異常點提供了綁定?」 – Vassilis

+1

我很確定這是最好的答案(即「不」)。 :-) – sheldonh

0

似乎有一個黑客可能做到這一點。這是不是很漂亮,但:

class Foo < Exception 
    attr_reader :call_binding 

    def initialize 
    # Find the calling location 
    expected_file, expected_line = caller(1).first.split(':')[0,2] 
    expected_line = expected_line.to_i 
    return_count = 5 # If we see more than 5 returns, stop tracing 

    # Start tracing until we see our caller. 
    set_trace_func(proc do |event, file, line, id, binding, kls| 
     if file == expected_file && line == expected_line 
     # Found it: Save the binding and stop tracing 
     @call_binding = binding 
     set_trace_func(nil) 
     end 

     if event == :return 
     # Seen too many returns, give up. :-(
     set_trace_func(nil) if (return_count -= 1) <= 0 
     end 
    end) 
    end 
end 

class Hello 
    def a 
    x = 10 
    y = 20 
    raise Foo 
    end 
end 
class World 
    def b 
    Hello.new.a 
    end 
end 

begin World.new.b 
rescue Foo => e 
    b = e.call_binding 
    puts eval("local_variables.collect {|l| [l, eval(l)]}", b).inspect 
end 

來源:How can I get source and variable values in ruby tracebacks?