Comment créer un enregistrement aujourd'hui par les rails activerecord?

112

Comment dois-je écrire l'instruction conditionnelle lorsque je veux obtenir tous les enregistrements qui ont été créés aujourd'hui?

Victor Lam
la source

Réponses:

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

PS: Cette réponse a été modifiée car la réponse de Harish Shetty était meilleure que la mienne. Comme ma réponse est acceptée. J'ai mis à jour cette réponse pour le support de la communauté

Mohit Jain
la source
4
On pourrait faire Post.where (created_at: Time.zone.now.beginning_of_day..Time.zone.now.end_of_day)
Rafael Oliveira
1
Il ne sert à rien de vérifier si quelque chose a été créé avant la fin d'aujourd'hui (puisque demain ne s'est pas encore produit).
jakeonrails
4
Bien que ce Post.where("created_at >= ?", Time.zone.now.beginning_of_day)soit très intelligent, je souscris Post.where(created_at: Time.zone.now.beginning_of_day..Time.zone.now.end_of_day). Il y a un point à faire de manière à pouvoir manipuler le temps. Par exemple, si vous testez, vous manipulerez probablement le temps et la première option ne fonctionnera pas. Vous voulez éviter ce genre d'échec possible futur qui prendra probablement un certain temps de débogage.
lucasarruda
121

Je sais que cette question a une réponse acceptée. La solution suggérée dans la réponse acceptée peut entraîner des problèmes de performances lorsque la taille de la table augmente.

En règle générale, si vous effectuez des recherches basées sur la created_atcolonne, ajoutez un index sur la table dans votre fichier de migration.

add_index :posts, :created_at

Maintenant, pour rechercher les enregistrements créés aujourd'hui:

Rails 3/4

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

Pour rechercher des articles créés un jour spécifique.

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

--------- OU -------------

Ajouter une méthode statique à votre modèle

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

Post.today #returns posts today

Rails 2

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

--------- OU -------------

Ajoutez un named_scope à votre modèle

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

Post.today #returns posts today
Harish Shetty
la source
1
Excellent point sur l'indexation. Je voulais juste préciser que l' scopeexemple de cet article concerne uniquement Rails 3, car il semble qu'il se trouve sous l'en-tête Rails 2. Dans Rails 2, vous devrez utiliser named_scopeplutôt que scope. De plus, dans Rails 3, vous pouvez utiliser de manière équivalente une méthode de classe def self.today where("created_at >= ?", Time.now.beginning_of_day) end qui est probablement plus propre que d'utiliser une portée dans ce cas, car elle vous permet de renoncer au lambda.
evanrmurphy
@evanrmurphy, merci d'avoir noté cela. J'ai une réponse fixe.
Harish Shetty
@evanrmurphy pouvez / devriez-vous réviser votre commentaire de "Rails 3 uniquement" à "Rails 3 et plus"?
kaichanvong
@kaichanvong Je ne connais pas Rails 4, alors j'aimerais dire "Rails 3 (et plus?)" mais SO ne me laisse pas modifier le commentaire: - /
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
la source
19

La réponse de Mohit Jain adaptée pour Rails3

Model.where "DATE(created_at) = DATE(?)", Time.now
thekindofme
la source
16

Rails 5.1 a une all_dayaide utile ici.

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

ou

Post.where(created_at: Date.parse("YYYY-MM-DD").all_day)
StevenClontz
la source
9

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

Cette "portée de nom" l'attribut avec le table_name.

Rafael Oliveira
la source
5

model.rb

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

posts_controller.rb

Post.posted_today
Parthiv
la source
2
@Pathiv, ça a l' between_periodair intéressant. Je n'ai trouvé aucune documentation à ce sujet. Pouvez-vous fournir un lien? Comment les rails choisissent-ils la colonne à comparer?
Harish Shetty
1

Pour une raison quelconque, aucune des autres solutions de cet article ni d'autres sur StackOverflow n'ont fonctionné pour moi (en utilisant Rails 4.2.4 et Ruby 2.2.3p173). C'est la seule requête que je pourrais obtenir pour travailler avec ma base de données Postgres:

Post.where("created_at >= TIMESTAMP 'now'")
Tim S
la source
-1

Pour interroger les enregistrements créés à partir d'aujourd'hui

Utilisez Scope avec Arel

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

Ensuite, nous pouvons l'utiliser

today_posts = Post.created_from_today
Hieu Pham
la source
where('created_at >= now()')ne trouverait que les éléments où le created_at était dans le futur.
PR Whitehead
Ouais, je le retirerais de la réponse, merci bien
Hieu Pham
Le problème que vous avez maintenant est que les enregistrements qui sont marqués avec des dates futures seraient présentés ainsi que ceux d'aujourd'hui. Si vous essayez d'éviter d'utiliser entre, vous devez également le spécifier .lteq(Time.zone.now.end_of_day)).
PR Whitehead
-4

Dans les rails 4.2.3 pour obtenir les enregistrements créés aujourd'hui, en utilisant mysql, utilisez ce qui suit.

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

ici, j'utilise plusieurs conditions si vous le souhaitez, vous pouvez le modifier pour une seule condition.

santu
la source