2011-09-10 11 views
1

私はEloquent Rubyの本(これまでの素晴らしい本)を読んでいて、blocs、params、scopeについて話している1つのセクションを理解していません。ここでパラメータ付きRubyブロック

class SomeApplication 
# Rest of the class omitted... 
    def do_something 
    with_logging('load', nil) { @doc = Document.load('book') } 

    # Do something with the document... 

    with_logging('save', @doc) { |the_object| the_object.save } 
    end 

    def with_logging(description, the_object) 
    begin 
     @logger.debug("Starting #{description}") 
     yield(the_object) 
     @logger.debug("Completed #{description}") 
    rescue 
     @logger.error("#{description} failed!!") 
     raise 
    end 
    end 
end 

本は、コードはそれが@docは、コードブロック内に自動的に表示されているためであることが必要以上に複雑であると言う...コードです。だから引数として渡す必要はありません。

彼が話しているparam @docまたは|the_object|はわかりません。不必要な複雑さを取り除くためにこのコードを変更した後、このコードはどのように見えるでしょうか?

with_logging('load', nil)で作成された@docがまだ表示されていることを意味しますか?その場合でも、下部のwith_loggingメソッドがどのようにそのメソッドにアクセスするのか分かりません。

答えて

1

@docinstance variableです。これはオブジェクトのスコープ(この場合はクラスSomeApplicationのインスタンス)内で定義され、通常インスタンスに「所属する」値を格納するために使用されます。インスタンス変数は、オブジェクトのインスタンスメソッドで常に使用できます。それらを属性にしない限り、オブジェクトの外側では使用できません。

あなたの混乱は、作者がメソッドdo_somethingの値をメソッドwith_loggingに渡しているラウンドアバウトの方法に起因している可能性があります。 with_loggingが呼び出されると、'save'@docという2つの引数を受け取ります。 with_loggingでは、ローカル変数description'save'に設定され、ローカル変数the_object@docに設定されています。次にyieldが引数the_objectで呼び出されます。the_objectは、with_loggingの2番目の呼び出しで定義されたコードブロックに渡されます。これは、匿名関数の並べ替えと考えることができます。もちろん、著者が指摘するように、with_loggingへの最初の呼び出しで@docが既に設定されていたので、引数として渡す必要はありません。その後、引数なしでyieldを呼び出し、その効果は同じになる

with_logging('load') { @doc = Document.load('book') } 

として
with_logging('save') { @doc.save } 

と最初:彼はように、第2の関数呼び出しを書かれている可能性があります。

0

これはインスタンス変数(@で示されている)なので、どのメソッドでもクラス全体で使用できます。

1

ブロック(およびlambda/procs)はクロージャです。これは、作成された環境内の変数にアクセスできることを意味します。@docはインスタンス変数なので、クラスのコンテキストで常にスコープ内にあります。 @docは、the_objectにバインドされた値ですが、これは不要です。改訂されたコードは次のようになります。

class SomeApplication 
    # Rest of the class omitted... 
    def do_something 
    with_logging('load') { @doc = Document.load('book') } 

    # Do something with the document... 

    with_logging('save') { @doc.save } 
    end 

    def with_logging(description) 
    begin 
     @logger.debug("Starting #{description}") 
     yield 
     @logger.debug("Completed #{description}") 
    rescue 
     @logger.error("#{description} failed!!") 
     raise 
    end 
    end 
end 
関連する問題