Madogiwa Blog

主に技術系の学習メモに使っていきます。

Ruby: lamdaを使っていい感じにロジックを変数に入れてスッキリ書く

みなさんRubylamdaを使っていますか?lamdaを使うとロジックを変数にいれて抽出するようなことが出来ます。これを使うと複雑なロジックを変数に入れて名前をつけられたり、いろいろとスッキリかけるケースが多そうな気がしてきたのメモしておきます📝

👇lamdaの基本的な使い方下記を参照してください

docs.ruby-lang.org

例えば、下記のようなブログの一覧の取得取得したあとにお気に入りが多いものだけを取得するロジックがあったとします。(DBで取得するときに除外すればいいじゃんという話は置いといて)

Blogs.where(published: true).to_a.select { |blog| blog.favorites.length > 100 }

これでも良いと思うんですが、除外するロジックが増えてきた場合にどうでしょう👀

Blogs.where(published: true).to_a.select do |blog|
  blog.favorites.length > 100 && blog.comments.length > 0
end

selectの中身がごちゃごちゃしてきたのと、do..endが入って行数が増えきて、ちょっと辛くなってきましたね😅

こういうときにはlamda(proc)を使ってあげるとスッキリかけます💪

下記がlamdaを使って書き直した例です。

pickup = ->(blog) { blog.favorites.length > 100 && blog.comments.length > 0 }
Blogs.where(published: true).to_a.select(&pickup)

どうでしょうかselect内の条件判定部分のロジックが抽出出来て読みやすくなっていますね👍

またlamdaを使うとメソッドやクラスに切り出しやすいのでリファクタリングもしやすいです👩‍🏭

メソッドの場合はlamdaの中のロジックを Blog側のインスタンスメソッドに定義してあげるとインターフェースもほぼ変えずにリファクタリング出来ます。

Blogs.where(published: true).to_a.select(&:pickup?)

class Blog
  def pickup?(user)
     blog.favorites.length > 100 && blog.comments.length > 0
  end
end

クラスの場合はこんな感じ。

Blogs.where(published: true).to_a.select{ |blog| BlogPickuper.call(blog) }

class BlogPickuper
  def self.call(blog)
      blog.favorites.length > 100 && blog.comments.length > 0
  end
end

このようにメソッド切るほどじゃないけど少し複雑だったり名前をつけてあげたい場合にlamdaを使ってあげるとスッキリかけますし今後のリファクタリングもしやすくなりそうですね👍