はっさんブログ

フォローするとお得なブログ

【Ruby】ブロック引数の使いどころになるパターン

参考になったらシェアいただけると幸いです!

背景

Ruby Advent Calender 2017、16日目の記事です。

最近までブロック引数をどの場面で使うのかわからなかったです。

プロダクトコードではあまり見たことがなく(経験が少ないからかも)、OSSのコードで良く見るなという印象でした。

一回うまく使えたことを皮切りに、使い所がパターン化できたので書いてみます。

使いどころ

メソッド内の処理の流れが類似しているが、ほんの少し内容が違う際の共通化

def hoge
  get_up         # 起きる
  wash_my_face   # 顔を洗う
  eat_breakfast  # 朝食を食べる 
  running        # 走る
  take_a_nap     # 昼寝をする
end

def fuga
  get_up         # 起きる
  wash_my_face   # 顔を洗う
  laugh          # 笑う
  wash_hands     # 手を洗う
  running        # 走る
  take_a_nap     # 昼寝をする
end

こう、流れは似てるんだけど内容が微妙に違うんだよな..

と思ったことありませんか?

こういうときにブロック引数(例ではyield)をもつメソッドを作成して共通化することができます。

ブロック引数を使う

def hoge
  piyo do
    eat_breakfast # 朝食を食べる
    running       # 走る
  end
end

def fuga
  piyo do
    laugh        # 笑う
    wash_hands   # 手を洗う
  end
end

def piyo
  get_up        # 起きる
  wash_my_face  # 顔を洗う
  yield
  running       # 走る
  take_a_nap    # 昼寝をする
end

yield ?? となった方はこちらを参考にしてください。

qiita.com

これによって、同じ流れだけど中身が違う処理が新たに増えても、piyo を利用して簡潔に書くことができます。

また、yieldに引数を与えてあげるとさらに柔軟に書くこともできます。

def hoge
  piyo do |friend|
    eat_breakfast  # 朝食を食べる
    running        # 走る
    friend.running # 友達が走る
  end
end

def fuga
  piyo do |friend|
    laugh         # 笑う
    wash_hands    # 手を洗う
    friend.laugh  # 友達が笑う
  end
end

def piyo
  friend = current_user.friend
  get_up         # 起きる
  wash_my_face   # 顔を洗う
  yield friend
  running        # 走る
  take_a_nap     # 昼寝をする
end

見ての通り、yieldに渡した変数は呼び出し先のブロック変数に代入されます。

メソッド内の処理の流れが類似しているが、ほんの少し内容が違う と思ったら使いどきなので、ぜひ思い出してみてください。

所感

DRYに書けてとても良いと思います。

参考になったら幸いです。