Puoi fare più del confronto in una data in una ricerca di Rails 3?


125

Ho questa ricerca in Rails 3:

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

Ma ho bisogno che la :date => p[:date]condizione sia equivalente :date > p[:date]. Come posso fare questo? Grazie per aver letto.

Risposte:


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

oppure puoi anche convertire tutto in notazione SQL

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

2
è sicuro? voglio dire se p [: date] proviene dall'input dell'utente, può causare un'iniezione SQL?
MhdSyrwan,

7
È sicuro a causa di where(). L'uso where()sfugge automaticamente all'input.
Simone Carletti,

34
Il commento di Simone non è del tutto vero; where()sfugge automaticamente all'input quando viene utilizzato nel formato mostrato sopra con punti interrogativi al posto delle variabili, con questi elencati successivamente nella chiamata di funzione. NON è sicuro usarlo in questo modo:Note.where("date > #{p[:date]}")
bdx

4
Vale anche la pena notare che l'uso where("user_id = ?",current_user.id)è più rischioso che where(user_id: current_user.id)nei casi in cui si uniscono modelli che hanno entrambi un user_idcampo. Utilizzando i mezzi prime SQL notazione è necessario includere la tabella chiarimenti da soli, ad esempio: where("notes.user_id = ?",current_user.id).
DreadPirateShawn,

1
Dovresti stare attento con questo, perché il fuso orario. Quando usi "" con Rails vai direttamente al database, e nel database la data viene salvata in UTC, ma dovresti essere in UTC + 5 per esempio, e questo non correggerà. Quindi assicurati di convertire la p [data] nel tuo attuale UTC prima di farlo
Paulo Tarud,

70

Se riscontri problemi in cui i nomi delle colonne sono ambigui, puoi fare:

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
Per qualche motivo, stavo ottenendo un errore con una colonna non trovata usando il metodo "where" di Simone su un server PostgreSQL ma funzionava in SQLite. Il tuo metodo ha funzionato su entrambi.
Plackemacher,

2

Puoi provare a usare:

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

equivalente in sql

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

Il risultato è:

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

E anche io sono cambiato

order('date ASC, created_at ASC')

Per

order(:fecha, :created_at)

0

Rails 6.1 ha aggiunto una nuova "sintassi" per gli operatori di confronto in wherecondizioni, ad esempio:

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

Quindi la tua query può essere riscritta come segue:

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

Ecco un link a PR dove puoi trovare altri esempi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.