Как получить запись, созданную сегодня rails activerecord?

113

Как мне написать условный оператор, если я хочу получить все записи, которые были созданы сегодня?

Виктор Лам
источник

Ответы:

220
Post.where(created_at: Time.zone.now.beginning_of_day..Time.zone.now.end_of_day)

PS: Этот ответ был изменен, поскольку ответ Хариша Шетти был лучше моего. Как мой ответ принят один. Я обновил этот ответ для поддержки сообщества

Мохит Джайн
источник
4
Можно было бы сделать Post.where (created_at: Time.zone.now.beginning_of_day..Time.zone.now.end_of_day)
Рафаэль Оливейра
1
Нет смысла проверять, было ли что-то создано до конца сегодняшнего дня (поскольку завтра еще не произошло).
jakeonrails
4
Пока Post.where("created_at >= ?", Time.zone.now.beginning_of_day)очень умен, я бы поддержал Post.where(created_at: Time.zone.now.beginning_of_day..Time.zone.now.end_of_day). Есть смысл действовать так, как вы можете управлять временем. Например, если вы тестируете, вы, вероятно, будете манипулировать временем, и тогда первый вариант не сработает. Вы хотите избежать такого рода возможных сбоев в будущем, которые могут потребовать некоторого времени на отладку.
lucasarruda
123

Я знаю, что на этот вопрос есть принятый ответ. Решение, предложенное в принятом ответе, может вызвать проблемы с производительностью при увеличении размера таблицы.

Обычно, если вы выполняете поиск на основе created_atстолбца, добавьте индекс таблицы в файл миграции.

add_index :posts, :created_at

Теперь, чтобы найти записи, созданные сегодня:

Рельсы 3/4

Post.where("created_at >= ?", Time.zone.now.beginning_of_day)

Для поиска сообщений, созданных в определенный день.

Post.where(:created_at => (date.beginning_of_day..date.end_of_day))

--------- ИЛИ -------------

Добавьте статический метод в вашу модель

class Post < ActiveRecord::Base
  def self.today
    where("created_at >= ?", Time.zone.now.beginning_of_day)
  end
end

Post.today #returns posts today

Рельсы 2

Post.all(:conditions => ["created_at >= ?", Time.zone.now.beginning_of_day])

--------- ИЛИ -------------

Добавьте named_scope в свою модель

class Post < ActiveRecord::Base    
  named_scope :today, lambda { 
    {
      :conditions => ["created_at >= ?", Time.zone.now.beginning_of_day]
    }
  }
end

Post.today #returns posts today
Хариш Шетти
источник
1
Замечательный момент об индексировании. Просто хотел уточнить, что scopeпример в этом посте предназначен только для Rails 3, поскольку похоже, что он находится под заголовком Rails 2. В Rails 2 вам нужно будет использовать named_scopeвместо scope. Кроме того, в Rails 3 вы могли бы эквивалентно использовать метод класса, def self.today where("created_at >= ?", Time.now.beginning_of_day) end который, вероятно, чище, чем использование области видимости в этом случае, поскольку он позволяет вам отказаться от лямбда.
evanrmurphy
@evanrmurphy, Спасибо, что заметили это. У меня есть четкий ответ.
Хариш Шетти
@evanrmurphy можно / нужно ли вам изменить свой комментарий с «Rails 3 only» на «Rails 3 и выше»?
kaichanvong
@kaichanvong Я не знаком с Rails 4, поэтому я хотел бы сказать «Rails 3 (и выше?)», но ТАК не позволяет мне редактировать комментарий: - /
evanrmurphy
30

MySQL:

Model.all :condition => ["DATE(created_at) = ?", Date.today] # rails 2
Model.where("DATE(created_at) = ?", Date.today) # rails 3

PostgreSQL:

Model.all :condition => ["created_at::date = ?", Date.today] # rails 2
Model.where("created_at::date = ?", Date.today) # rails 3
jigfox
источник
19

Ответ Мохита Джайна адаптирован для Rails3

Model.where "DATE(created_at) = DATE(?)", Time.now
thekindofme
источник
16

В Rails 5.1 есть all_dayполезный помощник.

Post.where(created_at: Date.today.all_day)

или

Post.where(created_at: Date.parse("YYYY-MM-DD").all_day)
Стивен Клонц
источник
9

Post.where(created_at: Time.zone.now.beginning_of_day..Time.zone.now.end_of_day)

Это "именует" атрибут с расширением table_name.

Рафаэль Оливейра
источник
5

model.rb

scope :posted_today, -> { posted_between_period(Time.now.midnight, Time.now.end_of_day) }

posts_controller.rb

Post.posted_today
Парфив
источник
2
@Pathiv, between_periodвыглядит интересно. Я не нашел к нему документации. Вы можете дать ссылку? Как рельсы выбирают столбик для сравнения?
Harish Shetty
1

По какой-то причине ни одно из других решений в этом посте и других решениях на StackOverflow у меня не сработало (с использованием Rails 4.2.4 и Ruby 2.2.3p173). Это единственный запрос, который я мог заставить работать с моей базой данных Postgres:

Post.where("created_at >= TIMESTAMP 'now'")
Тим С
источник
-1

Для запроса записей, созданных с сегодняшнего дня

Используйте область видимости с arel

class Post < ActiveRecord::Base    
  scope :create_from_today, -> {
    where(arel_table[:created_at].gteq(Time.zone.now.beginning_of_day))
  }
end

Тогда мы можем использовать это

today_posts = Post.created_from_today
Хиеу Фам
источник
where('created_at >= now()')найдет только те элементы, где в будущем был created_at.
PR Уайтхед
Да, я бы убрал это из ответа, приятно уловить, спасибо
Хиеу Фам
Проблема, с которой вы столкнулись, состоит в том, что записи, помеченные будущими датами, будут представлены так же, как и записи на сегодня. Если вы пытаетесь избежать использования между, вам также следует указать .lteq(Time.zone.now.end_of_day)).
PR Whitehead
-4

В rails 4.2.3 для получения записей, созданных сегодня, с использованием mysql используйте следующее.

@usergoals = Goal.where ("userid =: userid and Date (created_at) =: date", {userid: params [: id], date: Date.today})

здесь я использую несколько условий, если вы хотите, вы можете отредактировать его для одного условия.

Сант
источник