【Rails】スコープとクラスメソッドの違い
2020/08/11
普通に実装していたら違いなんてなくてどっちでもいいじゃんって思ってたけど、明確な違いがあった
今までたまたまそういう実装をしていないからハマらなかっただけで、いつかハマるかもしれないからメモしておく
スコープとクラスメソッドの違い
メソッドチェインができるようにスコープはActiveRecord::Relationを返すようになっている
どういう時にハマる可能性があるか
以下のようなfind_ageスコープを作成
app/models/user.rb
class User < ApplicationRecord
scope :find_age, ->(age) { find_by(age: age) }
end
条件に一致するレコードがある場合は特に問題ない
[1] pry(main)> User.find_age(27)
User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`age` = 27 LIMIT 1
=> #<User:0x00007f3b4dc32b18
id: 1,
name: "takagi",
age: 27,
created_at: Sat, 08 Aug 2020 22:07:38 JST +09:00,
updated_at: Sat, 08 Aug 2020 22:07:38 JST +09:00>
条件に一致するレコードがない場合は全件返ってくる
[1] pry(main)> User.find_age(30)
User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`age` = 30 LIMIT 1
=> User Load (0.2ms) SELECT `users`.* FROM `users`
[#<User:0x00007f3b4dd94448
id: 1,
name: "takagi",
age: 27,
created_at: Sat, 08 Aug 2020 22:07:38 JST +09:00,
updated_at: Sat, 08 Aug 2020 22:07:38 JST +09:00>,
#<User:0x00007f3b4dd94380
id: 2,
name: "tanaka",
age: 25,
created_at: Sat, 08 Aug 2020 22:07:53 JST +09:00,
updated_at: Sat, 08 Aug 2020 22:07:53 JST +09:00>,
#<User:0x00007f3b4dd942b8
id: 3,
name: "sato",
age: 32,
created_at: Sat, 08 Aug 2020 22:09:52 JST +09:00,
updated_at: Sat, 08 Aug 2020 22:09:52 JST +09:00>]
find_by
メソッドは条件に当てはまるレコードがないときはnilを返す仕様
スコープはActiveRecord::Relationを必ず返す仕様なので、nilではなくallと同じ結果のActiveRecord::Relationを返す
わかりやすくnilを返すスコープを用意
scope :return_nil, -> { nil }
[1] pry(main)> User.return_nil
=> User Load (0.4ms) SELECT `users`.* FROM `users`
[#<User:0x00007f3b4dd94448
id: 1,
name: "takagi",
age: 27,
created_at: Sat, 08 Aug 2020 22:07:38 JST +09:00,
updated_at: Sat, 08 Aug 2020 22:07:38 JST +09:00>,
#<User:0x00007f3b4dd94380
id: 2,
name: "tanaka",
age: 25,
created_at: Sat, 08 Aug 2020 22:07:53 JST +09:00,
updated_at: Sat, 08 Aug 2020 22:07:53 JST +09:00>,
#<User:0x00007f3b4dd942b8
id: 3,
name: "sato",
age: 32,
created_at: Sat, 08 Aug 2020 22:09:52 JST +09:00,
updated_at: Sat, 08 Aug 2020 22:09:52 JST +09:00>]
User.all
と同じ結果になる