Pouvez-vous faire plus que la comparaison sur une date dans une recherche Rails 3?


125

J'ai cette recherche dans Rails 3:

Note.where(:user_id => current_user.id, :notetype => p[:note_type], :date => p[:date]).order('date ASC, created_at ASC')

Mais j'ai besoin du :date => p[:date] condition soit équivalente :date > p[:date]. Comment puis-je faire ceci? Merci d'avoir lu.

Réponses:


226
Note.
  where(:user_id => current_user.id, :notetype => p[:note_type]).
  where("date > ?", p[:date]).
  order('date ASC, created_at ASC')

ou vous pouvez également tout convertir en notation SQL

Note.
  where("user_id = ? AND notetype = ? AND date > ?", current_user.id, p[:note_type], p[:date]).
  order('date ASC, created_at ASC')

2
est-ce sûr? je veux dire si p [: date] provient de l'entrée utilisateur, peut-il provoquer une injection SQL?
MhdSyrwan

7
C'est sûr à cause de where(). Utiliser where()échappe automatiquement l'entrée.
Simone Carletti

34
Le commentaire de Simone n'est pas entièrement vrai; where()échappe automatiquement l'entrée lorsqu'elle est utilisée dans le format indiqué ci-dessus avec des points d'interrogation à la place des variables, avec celles-ci répertoriées par la suite dans l'appel de fonction. Il n'est PAS sûr de l'utiliser de cette manière:Note.where("date > #{p[:date]}")
bdx

4
Il convient également de noter que l'utilisation where("user_id = ?",current_user.id)est plus risquée que where(user_id: current_user.id)dans les cas où vous fusionnez des modèles qui ont tous deux un user_idchamp. En utilisant les moyens de notation SQL brutes vous devez inclure les clarifications de table vous - même, par exemple: where("notes.user_id = ?",current_user.id).
DreadPirateShawn

1
Vous devez être prudent avec cela, car le fuseau horaire. Lorsque vous utilisez where avec "" Les rails vont directement à la base de données, et dans la base de données la date est enregistrée en UTC, mais vous devriez être en UTC + 5 par exemple, et cela ne corrigera pas. Assurez-vous donc de convertir le p [date] en votre UTC actuel avant de le faire
Paulo Tarud

70

Si vous rencontrez des problèmes où les noms de colonne sont ambigus, vous pouvez faire:

date_field = Note.arel_table[:date]
Note.where(user_id: current_user.id, notetype: p[:note_type]).
     where(date_field.gt(p[:date])).
     order(date_field.asc(), Note.arel_table[:created_at].asc())

2
Pour une raison quelconque, j'obtenais une erreur avec une colonne introuvable en utilisant la méthode "where" de Simone sur un serveur PostgreSQL mais cela fonctionnait dans SQLite. Votre méthode a fonctionné sur les deux.
plackemacher

2

Vous pouvez essayer d'utiliser:

where(date: p[:date]..Float::INFINITY)

équivalent en sql

WHERE (`date` >= p[:date])

Le résultat est:

Note.where(user_id: current_user.id, notetype: p[:note_type], date: p[:date]..Float::INFINITY).order(:fecha, :created_at)

Et j'ai changé aussi

order('date ASC, created_at ASC')

Pour

order(:fecha, :created_at)

0

Rails 6.1 a ajouté une nouvelle `` syntaxe '' pour les opérateurs de comparaison dans les whereconditions, par exemple:

Post.where('id >': 9)
Post.where('id >=': 9)
Post.where('id <': 3)
Post.where('id <=': 3)

Ainsi, votre requête peut être réécrite comme suit:

Note
  .where(user_id: current_user.id, notetype: p[:note_type], 'date >', p[:date])
  .order(date: :asc, created_at: :asc)

Voici un lien vers PR où vous pouvez trouver plus d'exemples.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.