こんにちはgengenです。
初めに言ってしまうと、Ruby2.7の始端無しRange(beginless range)がActiveRecordのwhereに渡せるので日付検索が全部Rangeできて便利というだけの記事です。
ActiveRecordのwhereにはRangeが渡せる
「ActiveRecordで日付・時刻の範囲検索をシンプルに書く方法」で詳しく紹介されてますが、そもそもwhereのハッシュ引数の値にRangeオブジェクトが渡せて、BETWEENと不等号を使い分けて上手いことクエリを作ってくれます。
User.where(activated_on: Date.new(2022,1,1)..Date.new(2022,12,31)).to_sql
=> "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"activated_on\" BETWEEN '2022-01-01' AND '2022-12-31'"
User.where(activated_on: Date.new(2022,1,1)...Date.new(2022,12,31)).to_sql
=> "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"activated_on\" >= '2022-01-01' AND \"users\".\"activated_on\" < '2022-12-31'"
始端無しRangeも使える
ここはRangeで表現したかったけど始端が無い事があるからな〜みたいな感じでそんなに使ってなかったりしたんですが、
そういえばRuby2.6の終端のないRangeに続き、Ruby2.7で始端の無いRangeが使えるようになってたんですよね。Railsの方も対応してました。
というわけで以下のように書けます。
# 始端無し
User.where(activated_on: ..Date.new(2022,12,31)).to_sql
=> "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"activated_on\" <= '2022-12-31'"
# 終端無し
User.where(activated_on: Date.new(2022,1,1)..).to_sql
=> "SELECT \"users\".* FROM \"users\" WHERE \"users\".\"activated_on\" >= '2022-01-01'"
賢い。上手いことクエリが作られてますね。
どんな範囲の検索でもActiveRecordに任せられてめっちゃスマートです。
終わりに
既に使ってる人からすれば何を今更という感じの話だったと思いますが、
始端無しRangeが頭からすっぽ抜けていて範囲検索にRangeを使っていない人が自分以外にも居ると信じて記事を書きました。ご参考になれば幸いです。