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, но если это можно сделать с объектами, отличными от строк, я бы хотел сделать это.

Ответ на потенциальный (мех)

Это отвратительно, но это можно сделать с диапазонами с использованием Time.at(0) и Time.at(Float::MAX). У меня такое чувство, что это может привести к столь же отвратительным SQL-запросам.

Ответ 1

Он не выглядит так, как если бы использовался базовый синтаксис хеша where для генерации большего или меньшего, чем запрос для временных меток. Самый простой и читаемый способ изложен в моем вопросе в разделе Current Simple Solution.

Другой способ сделать это - использовать AREL, но вы должны делать некоторые менее часто встречающиеся вызовы. Сначала вы можете получить дескриптор таблицы ARel AR, получить доступ к столбцу, передать результат больше, чем 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)

Ответ 2

Вы попробовали это?:

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')

Ответ 4

Попробуйте следующее:

User.where(last_deposit.gt(10.days.ago))