Können Sie an einem Datum in einer Rails 3-Suche mehr als nur einen Vergleich anstellen?

125

Ich habe diese Suche in Rails 3:

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

Aber ich brauche die :date => p[:date]Bedingung, um gleichberechtigt zu sein :date > p[:date]. Wie kann ich das machen? Danke fürs Lesen.

ben
quelle

Antworten:

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

oder Sie können auch alles in die SQL-Notation konvertieren

Note.
  where("user_id = ? AND notetype = ? AND date > ?", current_user.id, p[:note_type], p[:date]).
  order('date ASC, created_at ASC')
Simone Carletti
quelle
2
ist das sicher Ich meine, wenn p [: Datum] von Benutzereingaben stammt, kann es eine SQL-Injection verursachen?
MhdSyrwan
7
Es ist sicher wegen where(). Die Verwendung where()entgeht automatisch der Eingabe.
Simone Carletti
34
Simones Kommentar ist nicht ganz richtig; where()Die Eingabe wird automatisch ausgeblendet, wenn sie in dem oben gezeigten Format mit Fragezeichen anstelle von Variablen verwendet wird, die anschließend im Funktionsaufruf aufgelistet werden. Es ist NICHT sicher, es auf diese Weise zu verwenden:Note.where("date > #{p[:date]}")
bdx
4
Erwähnenswert ist auch, dass die Verwendung where("user_id = ?",current_user.id)riskanter ist als where(user_id: current_user.id)in Fällen, in denen Sie Modelle zusammenführen, die beide ein user_idFeld haben. Wenn Sie die SQL-Notation verwenden, müssen Sie die Tabellenerklärungen selbst einfügen, z where("notes.user_id = ?",current_user.id).
DreadPirateShawn
1
Sie sollten damit vorsichtig sein, weil Zeitzone. Wenn Sie verwenden, wo mit "" Rails direkt zur Datenbank gehen und in der Datenbank das Datum in UTC gespeichert wird, sollten Sie sich jedoch beispielsweise in UTC + 5 befinden, und dies wird nicht korrigiert. Stellen Sie also sicher, dass Sie das p [Datum] in Ihre aktuelle UTC konvertieren, bevor Sie es tun
Paulo Tarud
70

Wenn Sie auf Probleme stoßen, bei denen Spaltennamen nicht eindeutig sind, können Sie Folgendes tun:

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())
Sarah Vessels
quelle
2
Aus irgendeinem Grund wurde eine Fehlermeldung angezeigt, dass eine Spalte mit Simones "where" -Methode auf einem PostgreSQL-Server nicht gefunden wurde, aber in SQLite funktionierte. Ihre Methode hat bei beiden funktioniert.
Plackemacher
2

Sie können versuchen, Folgendes zu verwenden:

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

Äquivalent in SQL

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

Das Ergebnis ist:

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

Und ich habe mich auch verändert

order('date ASC, created_at ASC')

Zum

order(:fecha, :created_at)
Sesperanto
quelle
0

Rails 6.1 hat eine neue 'Syntax' für Vergleichsoperatoren unter whereBedingungen hinzugefügt , zum Beispiel:

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

So kann Ihre Anfrage wie folgt umgeschrieben werden:

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

Hier ist ein Link zu PR, wo Sie weitere Beispiele finden.

Marian13
quelle