LoginSignup
3
0

More than 1 year has passed since last update.

lambdaについて

Last updated at Posted at 2022-03-01

はじめに

has_manyで使われるクエリをカスタマイズしたかったので、その方法を調べたところ、初めて見る記述だったので、調べてみました。
以下に例を示します。Postに関連するlikeを作られた逆順(新しい順)で取得するための記述です。

author.rb
class Post < ApplicationRecord
 has_many :likes, -> { order(created_at: :desc) }
end

has_manyのスコープ

Railsガイドでは、次のように説明されています。

has_manyで使われるクエリをカスタマイズしたい場合があります。スコープブロックを用いてこのようなカスタマイズを行えます。

引用:has_manyのスコープについて

つまり、この以下の記述は、スコープブロックというものということです。

 -> { order(created_at: :desc) }

modelのスコープメソッド

ActiveRecordの機能の一つにscopeメソッドというものがあります。

よく使うクエリをスコープに設定すると、関連オブジェクトやモデルへのメソッド呼び出しとして参照できるようになります。スコープでは、where、joins、includesなど、これまでに登場したメソッドをすべて使えます。どのスコープメソッドも、常にActiveRecord::Relationオブジェクトを返します。

引用:Railsガイド スコープ

scopeメソッドの基本形

class Article < ApplicationRecord
  scope :スコープ名, -> { 条件式 }
end

article.rb
class Article < ApplicationRecord
  scope :published, -> { where(published: true) }
end

publishedというscopeを作成しています。矢印の後で、のスコープが行う処理をブロックで記述します。
今回の場合、articlesテーブルからpublishedカラムがtrueのデータを取得するというscopeとなります。

scopeメソッドの使い方

モデル.scope
article_controller.rb
@articles = Article.published
#=>@articlesには、publishedカラムがtrueのレコードが全て代入される。

scopeメソッドに引数を渡す

book.rb
class Book < ApplicationRecord
  scope :costs_more_than, ->(amount) { where("price > ?", amount) }
end
@books = Book.costs_more_than(100.10)
#=>booksテーブルからpriceが100.10より大きいレコードを取得して変数に代入します。
where("price > ?", amount)

の部分の"?"は、プレースホルダーというもので、第二引数の値が入ります。

参考:【Rails】 whereメソッドを使って欲しいデータの取得をしよう!

scopeメソッドを使用するメリット

  • 条件式に名前を付けられるので直感的なコードになる
  • 共通化により修正箇所が少なくて済む
  • 記述コードが短くなる

"->{}"はいったいなに?

"->{}"は、lambdaというものです。

lambdaとは

無名関数のことです。

関数を表現する式に文字ラムダ (λ) を使うという慣習からその名がある。

引用:ラムダ計算
名前の由来は、慣習によるものみたいです

無名関数とは

その名のとおり「名前のない関数」のことです。その正体は、RubyのProcオブジェクトです。

nameless_func = lambda { |n| n**2 }
nameless_func.(5)
# => 25

->(アロー関数)

->(アロー関数)はlambdaのリテラルです。
そのため、lambdaの部分を->(アロー関数)に置き換えることができます。

nameless_func = -> (n) { n**2 }
nameless_func.(5)
# => 25

[補足]RubyのProcオブジェクトとは

ブロックそれ自体は、ただの処理のかたまりで、オブジェクトではありません。そのため、Procオブジェクトとしてインスタンス化する必要があります。
参考:class Proc

まとめ

scopeメソッドについて

class Article < ApplicationRecord
  scope :published, -> { where(published: true) }
end

lambdaの部分が無名関数。つまり、名前の無い関数。
scopeメソッドは、無名関数にスコープ名を付すことで、使い回しができるようにしたものだったのですね。

has_manyのスコープについて

has_manyで使われるクエリをカスタマイズしたい場合は、スコープブロック(アロー関数を用いた無名関数)を用いてカスタマイズを行えます。

class Post < ApplicationRecord
 has_many :likes, -> { order(created_at: :desc) }
end
has_many(関連モデル名, scope=nil, オプション引数)

参考:has_many Railsドキュメント

参考

Active Record の関連付け
【Rails】 orderメソッドを使って取得したデータを並び替えよう!
Active Record クエリインターフェイス
[Rails]モデルのscopeメソッド
【Railsのモデルで使用】scopeのlambdaとは何なのか?使い方を紹介
class Proc

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0