คุณสามารถทำได้มากกว่าการเปรียบเทียบวันที่ในการค้นหา Rails 3 หรือไม่?


125

ฉันมีการค้นหานี้ใน Rails 3:

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

แต่ผมจำเป็นต้องมีเงื่อนไขที่จะเทียบเท่าการ:date => p[:date] :date > p[:date]ฉันจะทำเช่นนี้ได้อย่างไร? ขอบคุณที่อ่าน.

คำตอบ:


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

หรือคุณสามารถแปลงทุกอย่างเป็นสัญกรณ์ SQL

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

2
ปลอดภัยไหม ฉันหมายความว่าถ้า p [: date] มาจากอินพุตของผู้ใช้อาจทำให้เกิดการแทรก SQL ได้หรือไม่
MhdSyrwan

7
ปลอดภัยเพราะwhere(). การใช้where()จะหลีกเลี่ยงอินพุตโดยอัตโนมัติ
Simone Carletti

34
ความคิดเห็นของ Simone ไม่เป็นความจริงทั้งหมด where()หลีกเลี่ยงการป้อนข้อมูลโดยอัตโนมัติเมื่อใช้ในรูปแบบที่แสดงด้านบนโดยมีเครื่องหมายคำถามแทนตัวแปรโดยจะแสดงรายการในภายหลังในการเรียกฟังก์ชัน ไม่ปลอดภัยที่จะใช้ในลักษณะนี้:Note.where("date > #{p[:date]}")
bdx

4
สิ่งที่ควรสังเกตอีกอย่างwhere("user_id = ?",current_user.id)คือการใช้มีความเสี่ยงมากกว่าwhere(user_id: current_user.id)ในกรณีที่คุณรวมโมเดลที่ทั้งสองมีuser_idฟิลด์ โดยใช้สัญกรณ์ SQL where("notes.user_id = ?",current_user.id)ดิบหมายความว่าคุณจำเป็นต้องมีการชี้แจงโต๊ะตัวเองเช่น:
DreadPirateShawn

1
คุณควรระวังเรื่องนี้เพราะโซนเวลา เมื่อคุณใช้ where กับ "" Rails จะไปที่ฐานข้อมูลโดยตรงและในฐานข้อมูลวันที่จะถูกบันทึกเป็น UTC แต่คุณควรอยู่ใน UTC + 5 เป็นต้นซึ่งจะไม่ถูกต้อง ดังนั้นให้แน่ใจว่าได้แปลง p [วันที่] เป็น UTC ปัจจุบันของคุณก่อนที่จะทำ
Paulo Tarud

70

หากคุณพบปัญหาที่ชื่อคอลัมน์ไม่ชัดเจนคุณสามารถทำได้:

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
ด้วยเหตุผลบางประการฉันได้รับข้อผิดพลาดที่ไม่พบคอลัมน์โดยใช้วิธี "where" ของ Simone บนเซิร์ฟเวอร์ PostgreSQL แต่ทำงานใน SQLite วิธีการของคุณใช้ได้ทั้งสองอย่าง
plackemacher

2

คุณสามารถลองใช้:

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

เทียบเท่าใน sql

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

ผลลัพธ์คือ:

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

และฉันก็เปลี่ยนไปเช่นกัน

order('date ASC, created_at ASC')

สำหรับ

order(:fecha, :created_at)

0

Rails 6.1เพิ่ม 'ไวยากรณ์' ใหม่สำหรับตัวดำเนินการเปรียบเทียบในwhereเงื่อนไขตัวอย่างเช่น:

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

ดังนั้นจึงสามารถเขียนข้อความค้นหาของคุณใหม่ได้ดังนี้:

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

นี่คือลิงค์ไปยัง PRซึ่งคุณสามารถดูตัวอย่างเพิ่มเติมได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.