Rubyのブロックをメソッド間で受け渡す
ブロックとは
ブロックについてはこちらの記事が分かりやすかったです。
ブロックを引数にとるメソッドの定義
定義方法は、ブロックを引数にとることを明示する or しないの2通りがあります。
メソッドを呼び出したときの実行結果は同じです。
明示する
# 定義 def hoge_method(&block) block.call # ブロックの実行 end # 呼び出し hoge_method do puts 'hello world' end => hello world
明示しない
# 定義 def fuga_method yield # ブロックの実行 end # 呼び出し fuga_method do puts 'hello world' end => hello world
以下では明示する方法で記述していきます。
引数をとるブロックを渡す
ブロックを受け取るメソッドの中でいろいろ処理を行い、その結果をブロックで使用したい場合があると思います。
そういったときには、ブロックが引数をとるようにし、ブロックの実行時に処理結果を渡すようにします。
# 定義 def sample_method(&block) result = 'hello' # 処理 result << ' world' # 処理 block.call(result) # ブロックに result が渡される end # 呼び出し sample_method do |message| puts message # result の中身が message に入る end => hello world
ブロックを引数にとるメソッドを 別のメソッドで呼び出す
こういったことをしたい場合には以下のようにします。
少し複雑な気がしますが、ブロックを受け取って下へ下へと渡すだけです。
# 定義 def hoge_method(&block) # ブロックを引数にとるメソッドを呼び出すメソッド fuga_method(&block) # ブロックを渡す end def fuga_method(&block) # ブロックを引数にとるメソッド result = 'hello' result << ' world' block.call(result) end # 呼び出し hoge_method do |message| puts message end => hello world
この場合には yield
を使った方法では記述できないと思います。
( hoge_method
が受け取ったブロックを fuga_method
の呼び出し時に渡すことを明示する必要があるため。 )
間違ってたらごめんなさい。
ちなみに、
&block
の &
がブロックを Proc オブジェクトに変換しているようなので、 fuga_method
に Proc オブジェクトを渡すようにしても書けます。
Proc オブジェクトに変換されていることの確認
irb(main):001:0> def hoge_method(&block) irb(main):002:1> puts block.class irb(main):003:1> end => :hoge_method irb(main):004:0> hoge_method {} Proc => nil
Proc オブジェクトを渡すようにする
# 定義 def hoge_method(&block) # Proc オブジェクトを引数にとるメソッドを呼び出すメソッド fuga_method(block) # Proc オブジェクトを渡す end def fuga_method(block) # Proc オブジェクトを引数にとるメソッド message = 'hello' message << ' world' block.call(message) end # 呼び出し hoge_method do |message| puts message end => hello world