2011-10-04 11 views
7

で例外の瞬間の結合にアクセスすることができます。この例ではは私が持っていると言うルビー

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

rescue 
    puts $! 
    debugger 
end  

、私はaの値を取得したいです。 がbeginブロックで初期化されている場合、レスキュー時にアクセスできます。ただし、この例では、aはブロックローカルです。私が救助するとき、例外の瞬間に拘束力を得る方法はありますか?

+0

私はRBXはあなたに役立つことができ、いくつかのきちんとした 'Backtrace'オブジェクトを持っていた思い出すのにルビー渡って機能するソリューションを認識していないです。おそらくあなたが達成しようとしているものを拡大できますか? – riffraff

+0

@riffraffもし私がそれをよりよく説明できれば、私は知らない。私は(この例では)aの値を取得する必要があります。実世界のシナリオでは、2倍のブロックが繰り返しブロックであり、毎回CSVファイルから1行を取得するとします。ある時点(CSVファイルの行番号203445)で例外が発生します。さて、私はその行番号に行くことができます。特定の回線が「OK」であるかどうかをチェックするためにCSVファイルに格納します。あるいは、私は救助してデバッガセッションを開始することができます。この時点で。私はバインディングを見ることができるようにする必要があります。例外の瞬間に – Vassilis

+0

ありがとうございました。私が尋ねる理由は、同様の状況では、doブロック内にエラー管理コードがあるため、それは元の質問に答えることはできませんが、あなたのシナリオに合うように見えるだろう、私は恐れています。私が示唆できるのは、エラーがネイティブコードでない場合、呼び出し元バインディングを格納するためにraise/failをオーバーライドできますが、それは半分の解決策に過ぎません。 – riffraff

答えて

1

ブロック、rescueブロックをdoブロックの内側に置くことはできませんか?

+0

それは、私は、または私が欲しい他のどのような値の価値を確認することができないわけではありません。多分私の質問のタイトルは間違っています。私が書き直すことができれば、「バインディングにアクセスすることは可能ですか?」、あるいは「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?