Bisakah Anda melakukan lebih dari perbandingan pada tanggal dalam pencarian Rails 3?

125

Saya memiliki pencarian ini di Rails 3:

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

Tapi saya perlu :date => p[:date]kondisinya setara :date > p[:date]. Bagaimana saya bisa melakukan ini? Terima kasih sudah membaca.

ben
sumber

Jawaban:

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

atau Anda juga dapat mengubah semuanya menjadi notasi 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
sumber
2
apakah itu aman maksud saya jika p [: date] berasal dari input pengguna, dapatkah itu menyebabkan injeksi SQL?
MhdSyrwan
7
Aman karena where(). Menggunakan where()secara otomatis lolos dari input.
Simone Carletti
34
Komentar Simone tidak sepenuhnya benar; where()secara otomatis lolos input ketika digunakan dalam format yang ditunjukkan di atas dengan tanda tanya sebagai pengganti variabel, dengan mereka terdaftar setelah itu dalam panggilan fungsi. TIDAK aman menggunakannya dengan cara ini:Note.where("date > #{p[:date]}")
bdx
4
Juga patut dicatat, menggunakan where("user_id = ?",current_user.id)lebih berisiko daripada where(user_id: current_user.id)dalam kasus di mana Anda menggabungkan model yang keduanya memiliki user_idbidang. Menggunakan sarana notasi SQL mentah Anda perlu menyertakan klarifikasi meja sendiri, misalnya: where("notes.user_id = ?",current_user.id).
DreadPirateShawn
1
Anda harus berhati-hati dengan ini, karena zona waktu. Ketika Anda menggunakan "" Rails langsung ke basis data, dan dalam basis data tanggal disimpan dalam UTC, tetapi Anda seharusnya berada di UTC + 5 misalnya, dan ini tidak akan benar. Jadi pastikan untuk mengonversi p [tanggal] ke UTC Anda saat ini sebelum melakukannya
Paulo Tarud
70

Jika Anda mengalami masalah di mana nama kolom ambigu, Anda dapat melakukan:

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())
Kapal Sarah
sumber
2
Untuk beberapa alasan, saya mendapatkan kesalahan dengan kolom tidak ditemukan menggunakan metode "di mana" Simone pada server PostgreSQL tetapi itu bekerja di SQLite. Metode Anda berhasil pada keduanya.
plackemacher
2

Anda dapat mencoba menggunakan:

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

setara dalam sql

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

Hasilnya adalah:

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

Dan saya sudah berubah juga

order('date ASC, created_at ASC')

Untuk

order(:fecha, :created_at)
sesperanto
sumber
0

Rails 6.1 menambahkan 'sintaks' baru untuk operator perbandingan dalam wherekondisi, misalnya:

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

Jadi permintaan Anda dapat ditulis ulang sebagai berikut:

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

Berikut ini tautan ke PR tempat Anda dapat menemukan lebih banyak contoh.

Marian13
sumber