yieldとは
自分で定義したブロック付きメソッドでブロックを呼び出すときに使います。 yield に渡された値はブロック記法において | と | の間にはさまれた変数(ブロックパラメータ)に代入されます。
メソッド呼び出し(super・ブロック付き・yield) (Ruby 3.0.1 リファレンスマニュアル)
ブロックとはdo~endまた{}で囲まれているもの。eachやwhileメソッドたちのこと。ある処理の中で繰り返し使うeachやwhileをイテレータという。
yieldは『取って代わられる』という意味がある。
ブロックと引数の違いは?
引数は値。ブロックは処理。
yieldが作られた理由(予想)
if we face any situation we wanted to our method perform different functions according to calling block
メソッドが呼び出されたブロックによって異なる機能を実行することを望んでた
この辺りに書いてあることから予想。
複数のメソッドに共通の処理があり冗長的なコードに見えて『これまとめて〜』ってなって生まれたのかなと思いました。
使い方
viewで使う。application.html.erbとかで見ることが多いと思う。ヘッダーとフッターは共通のものを使えるので変えたいとこだけ変えるようにしましょう、ということ。
基本的に言い換えている部分の構成でメソッドに対しても使っていく。
<body>
<%= render 'layouts/header' %>
<%= yield %>
<%= render 'layouts/footer' %>
</body>
↓
<body>
<%= 共通部分 %>
<%= 変化させたいところ %>
<%= 共通部分 %>
</body>
共通の処理をcook_riceにまとめて、違う処理だけyeildで呼び出すようにしています。
def cook_rice
puts "お米6合入れる"
puts yield
puts "ご飯を盛る"
puts "食べる"
end
def nihon_mai
cook_rice do |_|
puts "お水6合入れる"
puts "お米すすぐ"
puts "40分待つ"
end
end
def thai_mai
cook_rice do |_|
puts "お水6合入れる"
puts "15分待つ"
end
end
yieldを使わない場合は以下のようになる。冗長的になっている。
def nihon_mai
puts "お米6合入れる"
puts "お米すすぐ"
puts "お水6合入れる"
puts "40分待つ"
puts "ご飯を盛る"
puts "食べる"
end
def thai_mai
puts "お米6合入れる"
puts "お水6合入れる"
puts "15分待つ"
puts "ご飯を盛る"
puts "食べる"
end
ブロックパラメータを設定して呼び出すことも可能。今回は水分量をパラメータに。
AMOUNT_OF_WATER = 6
def cook_rice
puts "お米6合入れる"
puts yield(AMOUNT_OF_WATER)
puts "ご飯を盛る"
puts "食べる"
end
def nihon_mai
cook_rice do |x|
puts "お米すすぐ"
puts "お水#{x}合入れる"
puts "40分待つ"
end
end
def thai_mai
cook_rice do |x|
puts "お水#{x}合入れる"
puts "15分待つ"
end
end
block_given?でブロック確認ができる。
def cook_rice
puts "お米6合入れる"
return puts "ブロックじゃないから炊かない" unless block_given?
puts yield(MIN)
puts "ご飯を盛る"
puts "食べる"
end
cook_rice
まとめ
yield・・呼び出し時にブロック処理を書くことで複数のブロック処理をyieldで呼び出せる。if文で処理を変えているところなどをyieldにまとめられる。
引数の数は違っていてもエラーにならない。