¿Se puede hacer más que la comparación en una fecha en una búsqueda de Rails 3?

125

Tengo esta búsqueda en Rails 3:

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

Pero necesito la :date => p[:date]condición para ser equitativo :date > p[:date]. ¿Cómo puedo hacer esto? Gracias por leer.

ben
fuente

Respuestas:

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

o también puedes convertir todo a la notación SQL

Note.
  where("user_id = ? AND notetype = ? AND date > ?", current_user.id, p[:note_type], p[:date]).
  order('date ASC, created_at ASC')
Simone Carletti
fuente
2
es eso seguro? Quiero decir, si p [: fecha] proviene de la entrada del usuario, ¿puede causar una inyección de SQL?
MhdSyrwan
77
Es seguro por eso where(). El uso where()escapa automáticamente a la entrada.
Simone Carletti
34
El comentario de Simone no es del todo cierto; where()se escapa automáticamente de la entrada cuando se usa en el formato que se muestra arriba con signos de interrogación en lugar de variables, que se enumeran después en la llamada a la función. NO es seguro usarlo de esta manera:Note.where("date > #{p[:date]}")
bdx
44
También vale la pena señalar que el uso where("user_id = ?",current_user.id)es más riesgoso que where(user_id: current_user.id)en los casos en que fusiona modelos que tienen un user_idcampo. El uso de los medios primas notación SQL que necesita para incluir la tabla aclaraciones por sí mismo, por ejemplo: where("notes.user_id = ?",current_user.id).
DreadPirateShawn
1
Debes tener cuidado con esto, porque la zona horaria. Cuando usa where con "" Rails, vaya directamente a la base de datos, y en la base de datos las fechas se guardan en UTC, pero debería estar en UTC + 5, por ejemplo, y esto no corregirá. Así que asegúrese de convertir la p [fecha] a su UTC actual antes de hacerlo
Paulo Tarud
70

Si encuentra problemas donde los nombres de columna son ambiguos, puede hacer:

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
fuente
2
Por alguna razón, recibía un error con una columna que no se encontraba usando el método "where" de Simone en un servidor PostgreSQL pero funcionaba en SQLite. Tu método funcionó en ambos.
plackemacher
2

Puedes intentar usar:

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

equivalente en sql

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

El resultado es:

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

Y yo también he cambiado

order('date ASC, created_at ASC')

por

order(:fecha, :created_at)
sesperanto
fuente
0

Rails 6.1 agregó una nueva 'sintaxis' para operadores de comparación en wherecondiciones, por ejemplo:

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

Entonces su consulta puede reescribirse de la siguiente manera:

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

Aquí hay un enlace a relaciones públicas donde puede encontrar más ejemplos.

Marian13
fuente