2012-02-22 6 views
1

私は現在この壁に戸惑っていますが、エラーが見つからないようですが、Rubyのブロックスコープのルールと関係していると思います。私はここでかなりの数の記事を読んだことがありますが、私は経験している問題と似ていないようです(あるいは、あまりにも見苦しいかもしれません)。 setter/gettersが定義されているインスタンス変数(ホスト名とOS)が2つしかないServerオブジェクトがあります。Rubyブロック変数スコープの問題?

問題は、sshチャネルデータを読み取っているブロックの途中にServerオブジェクトのOSを定義することです。私は、スクリプトを実行すると正しいデータを持っていることを知っています。しかし、ch.execブロックの最後に到達すると、Server.getOSはnilに戻ってしまいます。

アイデア?

注&コード: "hosts"はServerオブジェクトの配列です。

hosts.each do |server| 
begin 
    Net::SSH.start(server.getHostname, user , :password => password , :port=> port) do |ssh| 
     channel = ssh.open_channel do |ch| 
      ch.exec "uname" do |chan, success| 
       raise "could not execute uname command" unless success 
       chan.on_data do |c, data| 
        server.setOS = data 
        puts "local OS: #{server.getOS}" 
        # server.getOS = "AIX" here 
       end 
       chan.on_extended_data do |c, type, data| 
        puts data 
       end 
      end 

      puts "OS: #{server.getOS} -- hostname: #{server.getHostname}" 
      # server.getOS = "" here.. 

..そこからserver.getOSに基づいて処理が開始されますが、server.getOSはnilです。

答えて

0

それはここで何が起こっているのか明確ではないのですが、それは誤りの他のいくつかの種類が、操作の順序をトリガーするよう有望な候補は、スコーピングされていません。 execブロックは、非同期操作の場合はコード内のさらに下にあるputsコールの後で実行される可能性があります。

Rubyで定義されたブロックは、0回以上、任意の時点で実行できます。彼らはすぐに実行されるという保証はなく、非同期操作を行うときに少なくとも少し時間を過ぎることが期待されます。注意点としては

getXsetXの使用がxx=が慣例で使用される方法ですルビーの穀物に反します。最後に=というRubyのメソッド名は、ミューテータであると推定されます。

+0

"ブロックされていることを保証していません。すぐに実行されます。"それが本当であれば、どのような手順が意図どおりに動作することを保証しますか?私はおそらくあなたを誤解していますが、そのコメントはRubyがブロックを動かして無作為に実行するようなものです。 2 + 3 * 6は常に20になるはずです。 –

+0

@tadman torontoのレール市場はどうですか? – codecompleting

+0

Rubyブロックをメソッドに提供すると、そのブロックが実行されるかどうか、実行されるタイミングはわかりません。メソッドが提供する "契約"に精通し、それに応じて行動する必要があります。例えば、反復子はあなたのメソッドをすぐにN回実行しますが、ほとんどの非同期コールバックメソッドは一度呼び出されますが、何らかの条件のためにメソッドがいつ実行されないかはわかりません。それは無作為ではなく、ほとんど予測可能ですが、一度ブロックを指定すると、それが呼び出された方法に関して与えられたメソッドを慈悲にしています。 – tadman