Rails Model หาที่ไม่เท่ากัน


127

ฉันจะค้นหาระเบียนในฐานข้อมูลของฉันในสภาพที่ไม่เท่ากันได้อย่างไร ตอนนี้ฉันมีสิ่งนี้แล้ว แต่มีวิธีการพูดแบบรางที่แปลกใหม่หรือไม่?

GroupUser.where('user_id != ?',me)

สิ่งที่คุณมีคือ Rails 3 วิธีที่ดีในการทำฉันคิดว่า
Spyros

คำตอบ:


229

ใน Rails 4.x (ดูhttp://edgeguides.rubyonrails.org/active_record_querying.html#not-conditions )

GroupUser.where.not(user_id: me)

ใน Rails 3.x

GroupUser.where(GroupUser.arel_table[:user_id].not_eq(me))

หากต้องการลดความยาวให้สั้นลงคุณสามารถจัดเก็บGroupUser.arel_tableตัวแปรหรือหากใช้ภายในแบบจำลองGroupUserเช่นใน a scopeคุณสามารถใช้arel_table[:user_id]แทนGroupUser.arel_table[:user_id]

เครดิตไวยากรณ์ Rails 4.0 สำหรับคำตอบของ @ jbearden


แล้วในความสัมพันธ์ล่ะ? - has_many: group_users, -> {where.not (status: "Declined")}, through: groups, foreign_key: "user_id"
ajbraus

4
นอกจากนี้ยังใช้งานได้ดีเช่นกัน:GroupUser.where(other_condition: true).where.not(user_id: user_id)
Enrico Carlesso


26

วิธีเดียวที่คุณจะได้รับมันชอบเล่นอยู่กับMetaWhere

MetaWhere มีลูกพี่ลูกน้องรุ่นใหม่ที่เรียกว่าSqueelซึ่งอนุญาตให้ใช้รหัสเช่นนี้:

GroupUser.where{user_id != me}

มันเป็นไปโดยไม่ได้บอกว่าถ้านี่เป็น refactor ตัวเดียวที่คุณกำลังจะสร้างมันไม่คุ้มที่จะใช้อัญมณีและฉันจะยึดติดกับสิ่งที่คุณได้รับ Squeel มีประโยชน์ในสถานการณ์ที่คุณมีคำค้นหาที่ซับซ้อนจำนวนมากที่โต้ตอบกับรหัส Ruby


4
Meta ที่ไหนดี แต่งานนี้สามารถทำได้โดยไม่ต้องเพิ่มอัญมณี
tybro0103

1
@ tybro0103 แน่นอนว่างานนี้สามารถทำได้ (และวิธีการที่ OP ทำนั้นทำได้ดีอย่างสมบูรณ์แบบ) คำถามเกี่ยวกับการทำให้มันดูเพ้อฝัน ดังนั้นถ้าคุณคิดว่ามันสามารถทำได้โดยไม่ต้องมีอัญมณีฉันจะสนใจวิธีการทำเช่นนั้นมาก
Jakub Hampl

คำตอบของ Vikrant ให้คำตอบที่ไม่เกี่ยวข้องกับ sql หรือรวมถึงอัญมณีอื่น แต่ฉันได้รับการแก้ไขแล้วคำตอบของคุณเป็นรหัสที่เป็นมิตรกับสิ่งแวดล้อมมากที่สุด
tybro0103

1
เพิ่มอัญมณีเพื่อให้บรรลุภารกิจง่ายๆ ตีมอซซี่กับบา
ซูก้า

นี่คือ overkill
courtimas

23

ราง 4:

หากคุณต้องการที่จะใช้ทั้งสองไม่เท่ากันและเท่าเทียมกัน, คุณสามารถใช้:

user_id = 4
group_id = 27
GroupUser.where(group_id: group_id).where.not(user_id: user_id)

หากคุณต้องการใช้ตัวดำเนินการต่างๆ (เช่น. >, <) ในบางจุดคุณอาจต้องการเปลี่ยนสัญกรณ์ต่อไปนี้:

GroupUser.where("group_id > ? AND user_id != ?", group_id, user_id)

เกี่ยวกับอะไรGroupUser.where(group_id: group_id).where.not(user_id: user_id)?
Enrico Carlesso

@EnricoCarlesso ขอบคุณสำหรับการโพสต์ ฉันอัปเดตคำตอบของฉันเพื่อรวมคำแนะนำของคุณ ขอบคุณ
Rick Smith

9

คุณควรเสมอรวมถึงชื่อตารางในแบบสอบถาม SQL เมื่อต้องรับมือกับสมาคม

หากตารางอื่นมีuser_idคอลัมน์และคุณเข้าร่วมทั้งสองตารางคุณจะมีชื่อคอลัมน์ที่ไม่ชัดเจนในแบบสอบถาม SQL (เช่นปัญหา)

ดังนั้นในตัวอย่างของคุณ:

GroupUser.where("groups_users.user_id != ?", me)

หรือรายละเอียดเพิ่มเติมเล็กน้อย:

GroupUser.where("#{table_name}.user_id IS NOT ?", me)

โปรดทราบว่าหากคุณใช้แฮชคุณไม่จำเป็นต้องกังวลเกี่ยวกับเรื่องนี้เพราะ Rails จะดูแลให้คุณ:

GroupUser.where(user: me)

ใน Rails 4 ตามที่กล่าวโดย @ dr4k3 notมีการเพิ่มวิธีการสืบค้น:

GroupUser.where.not(user: me)

6

ใน Rails 3 ฉันไม่รู้อะไรเลย อย่างไรก็ตามฉันไม่แน่ใจว่าคุณทราบหรือไม่ว่าเงื่อนไขที่ไม่เท่ากันของคุณไม่ตรงกับค่า NULL (user_id) ถ้าคุณต้องการคุณจะต้องทำสิ่งนี้:

GroupUser.where("user_id != ? OR user_id IS NULL", me)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.