返り値がnilになり得るならscopeは使うな
事の発端
scope :showing, ->(now = Time.current) { where('start_at <= ?', now).where('end_at > ? OR end_at IS NULL', now) }
のような日時指定してデータ取得するみたいなscopeを書いた。
このとき一致するものはないため結果は[]
を期待していたがなぜか全件取得されていた。
不思議に思いscopeを使用せず直接クエリを発行すると期待する結果に。
なぜ???
原因
発行されたSQLを見合わせるも一言一句違わない…
なぜだ…と思いよく見たらscope指定した際のSQLの下に
Hoge Load (1.0ms) SELECT `hoges`.* FROM `hoges`
全件取得のSQLが発行されているではないか。
scopeの挙動
scopeはActiveRecord::Relation
を返す前提で設計されているらしく、結果がnil
の場合全件取得される仕様になっている。
解決策
返り値がnil
になり得るならおとなしくメソッド化しよう。
def self.showing now = Time.current where('start_at <= ?', now).where('end_at > ? OR end_at IS NULL', now) end