ActiveRecordで日付・時刻の範囲検索をシンプルに書く方法

本記事の続編「ActiveRecordのRangeHandlerクラスとRubyの範囲メソッド」もご覧ください。 こんにちは、hachi8833です。 Active Recordで日付範囲を指定して読み出そうとすると、おそらく次のようなコードになるでしょう。 Pattern.where(“updated_at BETWEEN ? AND ?”, from, to) 社内のSlackチャンネルのログを遡ってて、Active Recordでwhere(updated_at: range_obj_start..range_obj_end)のように、Rangeオブジェクトを#whereの値指定として渡せるというやりとりを見つけたので、確認してみました。 範囲演算子とは RubyのRangeオブジェクトでは、..と...という範囲演算子を使えます。 条件式以外の場所では式1から式2までの範囲オブジェクトを返します。範囲オブジェクトはRangeクラス のインスタンスです。... で生成された範囲オブジェクトは 終端を含みません。 Ruby 2.3.0 リファレンスマニュアル 終端を含まないのは..と...のどっちだったかときどきわからなくなったりしますね。 なお、数学用語では端の値を含む範囲を「閉区間」、端の値を含まない範囲を「開区間」と呼んでいます(Wikipedia: 区間(数学))。 Range#newでオブジェクトを生成できます。ここでの範囲演算子は..なので閉区間ですね。 Range.new(Time.zone.now, Time.zone.now.tomorrow) (pry-rails gemを導入したRailsコンソールで出力しました) ..と...で範囲指定 範囲演算子を思い出したところで、適当なRailsプロジェクトをbundle exec rails cでコンソール起動し、Active Recordの適当なモデル(ここではPatternというモデル)の”updated_at”カラムに次のクエリをそれぞれ実行してみます。両者の違いは、Rubyの範囲指定子..と...だけです。 Pattern.where(updated_at: Time.zone.today.beginning_of_day..Time.zone.today.end_of_day).to_sql Pattern.where(updated_at: Time.zone.today.beginning_of_day…Time.zone.today.end_of_day).to_sql 1番目の..のSQLでは、ストレートにBETWEENを使っています。 2番目の...のSQLでは、end_of_dayに終端を含まないよう、<を使って自動展開しています。 SELECT `patterns`.* FROM `patterns` WHERE (`patterns`.`updated_at` BETWEEN ‘2016-08-18 00:00:00’ AND ‘2016-08-18 23:59:59’) … Continue reading ActiveRecordで日付・時刻の範囲検索をシンプルに書く方法