Railsのscope内でfind_byを使った場合の挙動がヤバかったwwww

こんにちは!kossyです!



さて、今回はRailsのscope内でfind_byを使った場合の挙動について、
ブログに残してみたいと思います。

なお、タイトルはYoutubeのタイトルを意識してみました。特に意味はありません。



環境

Ruby 2.6.3
Rails 6.0.3
MacOS Mojave



scopeとは?

まずは公式Docの引用

scope(name, body, &block)

Adds a class method for retrieving and querying objects.
The method is intended to return an ActiveRecord::Relation object,
which is composable with other scopes.
If it returns nil or false, an all scope is returned instead.

A scope represents a narrowing of a database query,
such as where(color: :red).select('shirts.*').includes(:washing_instructions).

オブジェクトを取得および照会するためのクラスメソッドを追加します。
このメソッドは、他のスコープで構成可能なActiveRecord :: Relationオブジェクトを返すことを目的としています。
nilまたはfalseを返す場合は、代わりにallスコープが返されます。

scopeをモデルに定義すると、
Article.your_define_scope のように呼び出せるようになります。

同じようなActiveRecord文をメソッドのようにまとめたり、controllerに書きがちな複雑なActiveRecord文をモデルに寄せることができます。


nilまたはfalseを返す場合、allが実行される

さて、このscopeメソッドですが、nilまたはfalseが返り値になる場合、
all(SELECT `table_names`.* FROM `table_names`)が実行されるという挙動になります。

つまり、

scope :probably_all_scope, -> (name) {
  find_by: name
}

のようにnilが返り得るscopeを定義してしまうと、
allメソッドが実行される可能性があります。



公式Docにきちんと書いてありますので、ライブラリ内部に定義済みのメソッドを使うときは、
まずはDocを読んで挙動を把握するようにしてから使いましょう。