定義のようなもの
Called from inside a method body, yields control to the code block (if any) supplied as part of the method call. If no code block has been supplied, calling yield raises an exception.
yield can take an argument; any values thus yielded are bound to the block's parameters. The value of a call to yield is the value of the executed code block.
メソッド本体の内部から呼び出され、メソッド呼び出しの一部として提供されたコード・ブロック(もしあれば)に制御をゆだねる。コード・ブロックが提供されていない場合、yield を呼び出すと例外が発生します。
yieldは引数を取ることができ、yieldされた値はブロックのパラメータにバインドされます。yieldの呼び出しの値は、実行されたコード・ブロックの値です。
yieldはどんな時に使う
自分で定義したブロック付きメソッドでブロックを呼び出すときに使います。 yield に渡された値はブロック記法において | と | の間にはさまれた変数(ブロックパラメータ)に代入されます。
ブロックとは
コードの塊
do...endまたは{...}で囲まれたコード
一番簡単な例
def yield_ugoki
puts "処理開始"
yield
puts "処理終了"
end
yield_ugoki {puts "ブロック内の処理"}
# 出力:
# 処理開始
# ブロック内の処理
# 処理終了
{puts "ブロック内の処理"} がブロック
ブロックパラメータを使った例
def yield_ugoki
puts "処理開始"
yield("こんにちは") # 引数を渡す
puts "処理終了"
end
# ブロックパラメータ message を |message| で受け取る
yield_ugoki {|message| puts "ブロック内の処理: #{message}"}
railsでの使用例
<!-- app/views/layouts/application.html.erb -->
<html>
<head>
</head>
<body>
<h1>共通ヘッダー</h1>
<%= yield %>
<footer>共通フッター</footer>
</body>
</html>
ルーティングに基づいて特定コントローラのアクションが実行される
アクションに対応するビューファイルがレンダリング
ビューのメインbodyは、常に「名前のない」yieldの位置でレンダリングされます。
という流れのよう
変数やメソッドを使えばいいんじゃね?
変数
あくまでデータを扱うもの、振る舞いは代入できない。
関数(コードは全て引用)
def hello()
return “Hello World!”
end
hello() #=> “Hello World!”
def hello2()
return yield
end
hello2(){“Hello World!”} #=> “Hello World!"
この例だと特に便利さはわからない、、、
def double()
yield
yield
end
double(){print “Hi!”} #=>”Hi!Hi!”
この例だと、振る舞いを2回呼び出せるという利点を見出せる。
def greet(name)
print "You see #{name}. "
puts yield(name)
end
greet('Dave'){|person| "Hi #{person}!"} #=> "You see Dave. Hi Dave!"
greet('Dave'){|person| "#{person} says hello!"} #=> "You see Dave. Dave says hello!"
同じメソッドを使いながら、違った挨拶を出力できる
greetメソッドを変形せずに(関心の分離?)、違った挨拶を出力できる
参考文献
https://docs.ruby-lang.org/ja/latest/doc/spec=2fcall.html#yield
https://railsguides.jp/layouts_and_rendering.html
https://dev.to/nwdunlap17/an-introduction-to-yield-in-ruby-and-filtering-class-instances-549j
https://ruby-doc.org/docs/keywords/1.9/Object.html