web-dev-qa-db-ja.com

Rails `where`クエリより短い時間

セットアップ

Railsのwhereメソッドは、ハッシュ内の範囲を取得して、範囲内の値を検索するクエリを生成できます。例えば:

_User.where(cash_money: 10..1000)
#=> SELECT `users`.* FROM `users`  WHERE (`users`.`cash_money` BETWEEN 10 AND 1000)
_

これは、次のようなタイムスタンプでも使用できます。

_User.where(last_deposit: 10.days.ago..1000.days.ago)
#=> SELECT `users`.* FROM `users`  WHERE (`users`.`last_deposit` BETWEEN '2014-05-19 14:42:36' AND '2011-09-02 14:42:36')
_

このようなハッシュ構文を使用して、数値に対して単純な「より小さい」または「より大きい」を実行できることがわかりました

_User.where(cash_money: 10..Float::INFINITY)
#=> SELECT `users`.* FROM `users`  WHERE (`users`.`cash_money` >= 10)
_

_-Float::INFINITY_でも同じことができます。

質問

次のようなクエリを取得できるように、タイムスタンプでこれを行う方法はありますか?

_SELECT `users`.* FROM `users`  WHERE (`users`.`last_deposit` >= '2014-05-19 14:42:36')
_

_Float::INFINITY_または_Date::Infinity_はどちらも_ArgumentError: bad value for range_でエラーになるため、範囲を指定して使用することはできません。

現在のシンプルなソリューション

_User.where('`users`.`last_deposit` >= ?', 10.days.ago)
_

同じSQLを生成しますが、これが文字列以外のオブジェクトで実行できる場合は、そうしたいと思います。

潜在的な(Meh)回答

これはお粗末なことですが、Time.at(0)Time.at(Float::MAX)を使用して範囲で実行できます。しかし、これらは同様にひどいSQLクエリをもたらす可能性があると私は感じています。

18
Aaron

編集

これはRails 5!

User.where(last_deposit: 10.days.ago..DateTime::Infinity.new)

sQLを生成します

SELECT `users`.* FROM `users` WHERE (`users`.`last_deposit` >= '2018-06-30 17:08:54.130085').

オリジナル(およびRails <5)回答

基本的なwhereハッシュ構文を使用してタイムスタンプのより大きいまたはより小さいクエリを生成する方法があるかのようには見えません。最も簡単で読みやすい方法は、私の質問のCurrent Simple Solutionに概説されています。

別の方法ではARelを使用しますが、あまり見られない呼び出しを行う必要があります。まず、ARクラスのARelテーブルへのハンドルを取得し、列にアクセスして、gt以上、gteq以上、lt、および/またはlteqへの引数を持つwhereメソッド以下。

上記の状況では、これは次のように行われます。

last_deposit_column = User.arel_table[:last_deposit]
last_deposit_over_ten_days_ago = last_deposit_column.gteq(10.days.ago)
User.where(last_deposit_over_ten_days_ago)
15
Aaron

これを試しましたか?:

User.where(last_deposit: Time.at(0)...10.days.ago)

SQL:

SELECT `users`.* FROM `users`  WHERE (`users`.`last_deposit` >= '1970-01-01 00:00:00' AND `users`.`last_deposit` < '2015-01-10 17:15:19')
11
Richard

適切な無限大を使用する必要があります。タイムスタンプはDateTimeではなくDateです。代わりに_DateTime::Infinity.new_を使用するか、負の無限大の場合はDateTime::Infinity.new(-1)を使用してください。

関連: Rubyで「無限の時間」を表現する方法はありますか?

0
Nuclearman