lambdaについて

## はじめに

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

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

## has_manyのスコープ
Railsガイドでは、次のように説明されています。

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

引用：[has_manyのスコープについて](https://railsguides.jp/association_basics.html#has-many%E3%81%AE%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)

つまり、この以下の記述は、**スコープブロック**というものということです。
~~~ruby
 -> { order(created_at: :desc) }
~~~

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

引用：[Railsガイド　スコープ](https://railsguides.jp/active_record_querying.html#%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97)
### scopeメソッドの基本形

~~~ruby
class Article < ApplicationRecord
  scope :スコープ名, -> { 条件式 }
end
~~~
例
~~~ruby:article.rb
class Article < ApplicationRecord
  scope :published, -> { where(published: true) }
end
~~~
publishedというscopeを作成しています。矢印の後で、のスコープが行う処理を**ブロック**で記述します。
今回の場合、articlesテーブルからpublishedカラムがtrueのデータを取得するというscopeとなります。

### scopeメソッドの使い方
~~~ruby
モデル.scope
~~~
~~~ruby:article_controller.rb
@articles = Article.published
#=>@articlesには、publishedカラムがtrueのレコードが全て代入される。
~~~

### scopeメソッドに引数を渡す
~~~ruby:book.rb
class Book < ApplicationRecord
  scope :costs_more_than, ->(amount) { where("price > ?", amount) }
end
~~~
~~~ruby
@books = Book.costs_more_than(100.10)
#=>booksテーブルからpriceが100.10より大きいレコードを取得して変数に代入します。
~~~
~~~ruby
where("price > ?", amount)
~~~
の部分の"？"は、プレースホルダーというもので、第二引数の値が入ります。

参考：[【Rails】 whereメソッドを使って欲しいデータの取得をしよう！](https://pikawaka.com/rails/where)

### scopeメソッドを使用するメリット
- 条件式に名前を付けられるので直感的なコードになる
- 共通化により修正箇所が少なくて済む
- 記述コードが短くなる

## "->{}"はいったいなに？
"->{}"は、**lambda**というものです。

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

引用：[ラムダ計算](https://ja.wikipedia.org/wiki/%E3%83%A9%E3%83%A0%E3%83%80%E8%A8%88%E7%AE%97)
名前の由来は、慣習によるものみたいです

### 無名関数とは
その名のとおり「名前のない関数」のことです。その正体は、RubyのProcオブジェクトです。
~~~ruby
nameless_func = lambda { |n| n**2 }
nameless_func.(5)
# => 25
~~~

#### ->(アロー関数)
->(アロー関数)はlambdaのリテラルです｡
そのため、lambdaの部分を->（アロー関数）に置き換えることができます。
~~~ruby
nameless_func = -> (n) { n**2 }
nameless_func.(5)
# => 25
~~~

#### [補足]RubyのProcオブジェクトとは
ブロックそれ自体は、ただの処理のかたまりで、オブジェクトではありません。そのため、Procオブジェクトとしてインスタンス化する必要があります。
参考:[class Proc](https://docs.ruby-lang.org/ja/latest/class/Proc.html)

## まとめ
### scopeメソッドについて
~~~ruby
class Article < ApplicationRecord
  scope :published, -> { where(published: true) }
end
~~~
lambdaの部分が無名関数。つまり、名前の無い関数。
scopeメソッドは、無名関数にスコープ名を付すことで、使い回しができるようにしたものだったのですね。

### has_manyのスコープについて
has_manyで使われるクエリをカスタマイズしたい場合は、スコープブロック（アロー関数を用いた無名関数）を用いてカスタマイズを行えます。
~~~ruby
class Post < ApplicationRecord
 has_many :likes, -> { order(created_at: :desc) }
end
~~~
~~~ruby
has_many(関連モデル名, scope=nil, オプション引数)
~~~
参考：[has_many Railsドキュメント](https://railsdoc.com/page/has_many)


## 参考
[Active Record の関連付け](https://railsguides.jp/association_basics.html)
[【Rails】 orderメソッドを使って取得したデータを並び替えよう！](https://pikawaka.com/rails/order)
[Active Record クエリインターフェイス](https://railsguides.jp/active_record_querying.html#%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97)
[[Rails]モデルのscopeメソッド](https://zenn.dev/yusuke_docha/articles/ca0637ccc8d01f)
[【Railsのモデルで使用】scopeのlambdaとは何なのか？使い方を紹介](https://shinmedia20.com/rails-scope-lambda)
[class Proc](https://docs.ruby-lang.org/ja/latest/class/Proc.html)