raiils の初学者です。
scopeについてよく分かってなかったのですが、絞り込み検索機能を実装するにあたって、「scope使えば実装できるかも」となって、実際に使ってみたので、まとめたいと思います。
scopeを使うことになった経緯
そもそも今までは絞り込み検索機能はwhereを使ってDBからデータを絞って取り出せばいいや。と考えていました。
ただ、絞り込む要素がいくつかあったとして、そのうちのどれかをユーザーが選択しなかった場合の処理。
ようは下の写真のように
「開始日付」、「終了日付」、「開始時刻」、「終了時刻」、「方面」、「駅」
と絞り込み要素が複数存在した場合の絞り込み型として
@posts = Post.where('date => ?', params[:post][:start_date]).where('date =< ?', params[:post][:end_date]).where('date => ?', [:post][:start_time])・・・
といった感じでwhereをつなげてしまうと、
「今回は 開始日付と 終了日付 だけで絞り込みたい」のような一部だけの絞り込みというのが出来ず、どの項目も必ず選択することになってしまいます。
以前、同じような状況に陥った際に
if params[:post][:start_date]
・・・
というように、if文で分岐させて、if文の中にwhereを使った絞り込み処理をしていたのですが、今回のように項目が多いとif文がめちゃ長くなってしまいます。
そこでググってみると、scopeを使って絞り込み検索機能を実装出来そうだったのでscopeを使ってみました。
そもそもscopeって?
「なんかmodelにvalidation設定する際に使ったことあったけど、結局何?」 となったのですが、ようは
scopeを使えば、where、joins、includesなどの複数クエリをまとめて、1つのメソッドとして定義できる
ということみたいです。(違ったらごめんなさい)
scopeを使うと良いこと
scope1つに1つにif文をつけられるので、 paramsに値が入ってない場合は(ユーザーが全項目を選択してなくても)
「全選択」扱いにすることができました。
以下が実際に書いたコードです。
実際に書いたコード
Post.rb
# 検索の際の期間絞り込み
scope :s_duration, ->(start_date) { where("date >= ?", start_date) if start_date.present? }
scope :e_duration, ->(end_date) { where("date <= ?", end_date) if end_date.present? }
# 検索の際の時間絞り込み scope :s_time, ->(start_time) { where("time >= ?", start_time) if start_time.present? }
scope :e_time, ->(end_time) { where("time >= ?", end_time) if end_time.present? }
# 検索の際の方面と駅の絞り込み scope :direction, ->(direction) { where("direction = ?", direction) if direction.present? }
scope :station, ->(station) { where("station_id = ?", station) if station.present? }
post.controller.rb
def posts_search
s_time = params[:post][:start_time]
e_time = params[:post][:end_time]
s_date = params[:post][:start_date]
e_date = params[:post][:end_date]
direction = params[:post][:direction]
station = params[:post][:station]
@posts = Post.s_duration(s_date).e_duration(e_date).s_time(s_time).e_time(e_time).direction(direction).station(station)
end
本当はもっと短く書けるのかもしれませんが、今回はこれで良しとしました。
詳しくはrailsのサイトに載っています。
参考サイト
https://qiita.com/ozin/items/24d1b220a002004a6351
https://railsguides.jp/active_record_validations.html