ransackを使って日付検索&プルダウン選択する
実装したいこと
前提
ransack導入済み
実装の流れ
- コントローラーにransack用の設定
- ransackの検索条件をカスタムする
- Viewに反映させる
Controller
def index @q = Board.ransack(params[:q]) @boards = @q.result(distinct: true).includes(%i[user]).order(created_at: :desc).page(params[:page]) end
Custom Predicates
「2020年9月1日〜2020年9月3日までに作成された掲示板」のように日付を指定して掲示板を検索したいです。
ransack
公式のpredicate
リストの中から探してみます。
ransackのpredicateとは?
公式は、READ.MEだけでなくWikiも読むようにしないとダメですね。スルーしてました。
predecateは「述語」という意味です。例えば、cont
はcontainの略で、属性に「〜を含んでいる」ものを検索します。
The primary method of searching in Ransack is by using what is known as predicates. Predicates are used within Ransack search queries to determine what information to match. For instance, the cont predicate will check to see if an attribute called "first_name" contains a value using a wildcard query:
Basic Searching · activerecord-hackery/ransack Wiki · GitHub
gteq
(greater then or equal to) 〜以上
lteq
(less then or equal to) 〜以下
を使えば実装できそうですが、これで実装したところ、
「9月1日00時〜9月3日00時」までとなり、前日分の検索しかできませんでした。
「9月1日00時〜9月3日23時59分599999…」のような日付設定にしたいです。
公式のWikiに
Ransackのpredecatesはカスタムできるよ、と例が書いてあります。
これで設定していきます。コメント部分は公式のコメントの翻訳です。
Custom Predicates · activerecord-hackery/ransack Wiki · GitHub
Ransack.configure do |config| config.add_predicate 'lteq_end_of_day', #設定するpredicateに名前をつける arel_predicate: 'lteq', #使いたいpredicate formatter: proc { |v| v.end_of_day } # 受け取った値をどうフォーマットするか end
Arelとは
ArelはActive Recordの内部で使用されるSQL生成ライブラリです。
end_of_day
end_of_dayっていきなり使ってるけど定義しなくていいの??と思ったら、
end_of_day
っていうメソッドがあるんですね。知らなかったです。
end_of_day() public Converts Date to a Time (or DateTime if necessary) with the time portion set to the end of the day (23:59:59) https://apidock.com/rails/Date/end_of_day
View
<%= f.date_field :created_at_gteq, include_blank: true, class: 'form-control'%>〜 #「〜」と書くと分かりやすい <%= f.date_field :created_at_lteq_end_of_day, #さっき設定したやつ include_blank: true, class: 'form-control'%>
できあがり。
特に設定しなくてもカレンダー表示になった。Bootstrapがやってくれているのかな?謎