yujiro's blog

「インターネット上で正しい答えを得る最善の方法は、質問することではない。間違った答えを投稿することだ」by ウォード・カニンガム。 辛辣なコメントお待ちしております。

【Rails】 scope は 常に ActiveRecord_Relation を返す素晴らしいやつ

Rails で様々な条件で複合検索ができる画面を実装していて、フォームから受け取った値をそのままモデルに渡してコントローラは条件分岐なしにスッキリ実装したかった。 何の気なしに以下のようなコードを書いた。

Post.hoge_method(params[:hoge]).search(params[:word]).another_method....

例えば search の部分は form から渡ってきた値をモデルに渡して値がなければ その部分のクエリを組み立てないでほしかった。

def self.search(w)
  if w.present?
    where('title like :title or description like :description', {title: "%#{w}%", description: "%#{w}%"})
  else
    ...
  end
end

ここで少し思考が停止して、

else のとき、何を返せばいいんだ??となった。

調べてみたら大変素晴らしい記事を見つけた。

【Rails】なぜクラスメソッドよりもスコープを使うべきなのか?

スコープの中で発行されたクエリがnilになる場合は、.allを返すように設計されているので、スコープの返り値を気にせずチェーンを繋げることができます。

そうか。。さっきの部分は

else
    all
end

て書けば良いんだけど scope を使えばその必要すらなくて

scope :search, -> (w) { where('title like :title or description like :description', {title: "%#{w}%", description: "%#{w}%"}) if w.present? } 

だけでよいそう。 scope がnilを返したらall ()を返すようになっているのは全然知りませんでした。