Запрос Rails: сравните вычисление двух значений атрибута

У меня есть модель, продукт, который имеет как :created_at отметка времени и :expiration_in_days приписывать. Продукты считаются просроченными через определенное количество дней после их создания. Как мне написать запрос, который возвращает только товары, срок годности которых не истек?

Rails 4, Ruby 2.1, PG 0.17

Я пробовал подобные запросы, но безуспешно:

#product.rb
def self.not_expired
  where('created_at + expiration_in_days * 86400 >= ?', Time.now)
end

У меня есть чистая версия Ruby, которая работает нормально, она только медленнее:

#product.rb
def self.not_expired
  select{ |p| (p.created_at.to_i + p.expiration_in_days * 86400) >= Time.now.to_i}
end
  • обратите внимание, что вычисление 86400 преобразует целое число:expiration_in_days в секунды

Любые указатели на более продвинутые запросы Rails, чем документация ( http://guides.rubyonrails.org/active_record_querying.html), также будут приветствоваться.

Заранее спасибо.

3 ответа

Решение

Попробуй это:

def self.not_expired
  where("created_at + (expiration_in_days * 86400)::text::interval >= ?", Time.now)
end

ОБНОВЛЕНИЕ: Добавить ссылки

Вы можете узнать больше о функции даты и времени здесь.

Учитывая ваш случай имеет особое требование, которое является значением expiration_in_days столбец в таблице, мы не можем использовать created_at + interval expiration_in_days day, Вместо этого нам нужно набрать приведение его значения к interval, Но вы не можете набирать приведение прямо к целому числу, поэтому мы приводим его к text первый.

Я не уверен, что это сработает, но попробуйте что-то вроде этого

def self.not_expired
  where("TIMESTAMP created_at + INTERVAL '1 day' * expiration_in_days >= NOW()")
end

A + B > C истинно, если A <= C - B

Таким образом, вместо того, чтобы пытаться добавить время истечения в созданный_кат, вычтите время истечения из Time.now.

def expiration_threshold
  Time.now - amount_of_time # I'm not sure what type to use
end

def self.not_expired
  where( "created_at > ? ", expiration_threshold )
end

Я всегда был немного озадачен тем, какой тип Rails/Ruby понадобится при работе с различными датами / временем, вам, возможно, придется поиграть.

Другие вопросы по тегам