ค้นหา () ด้วยศูนย์เมื่อไม่มีระเบียน


98

ในโปรแกรมรางปัจจุบันของฉันเมื่อฉันใช้สิ่งต่างๆเช่น

 user = User.find(10)

เมื่อไม่มีผู้ใช้ที่มี ID = 10 ฉันจะมีข้อยกเว้นเช่น:

ActiveRecord::RecordNotFound: Couldn't find User with ID=10

ฉันสามารถรับศูนย์แทนการเพิ่มข้อยกเว้นได้หรือไม่เมื่อฉันทำบางสิ่งเช่น:

unless user = Challenge.find(10)
  puts "some error msg"         
end

ฉันแค่อยากได้ศูนย์เมื่อไม่มีบันทึกและฉันไม่ต้องการใช้ start / rescue

ขอบคุณ


คำตอบ:


175

ใช่เพียงแค่ทำ:

Challenge.find_by_id(10)

สำหรับ Rails 4 และ 5:

Challenge.find_by(id: 10)

12
แปลก! ฉันไม่เคยเดาเลยว่าสิ่ง.find_by_*นั้นจะกลับมาเป็นศูนย์และ.findจะไม่กลับมา
ddavison

สิ่งนี้มีการเปลี่ยนแปลงในราง 4 ดูคำตอบนี้stackoverflow.com/a/26885027/1438478สำหรับวิธีใหม่ในการค้นหารายการโดยใช้แอตทริบิวต์เฉพาะ
Fralcon

ฉันพบปัญหาแปลก ๆ กับ Rails 4.2 ซึ่งเมื่อคุณส่งแฮชเป็น 'x' ไป Something.find_by(id: x)มันจะสร้างคำสั่ง SQL ที่มีคู่แอตทริบิวต์ / ค่าทั้งหมดของแฮชเป็นส่วนหนึ่งของคำสั่ง WHERE ดูเหมือนข้อผิดพลาดของ Rails สำหรับฉัน
Tilo

ทางรถไฟ (3, 4 หรือ 5) สร้างแบบไดนามิกแงสำหรับแอตทริบิวต์แบบได้รวมถึงทุกfind_by_... :idดังนั้นChallenge.find_by_id(10)ควรทำงานโดยไม่คำนึงถึงเวอร์ชัน Rails
Arta

ตามที่ระบุไว้โดย @MohamedIbrahim ด้านล่างคุณสามารถทำได้:Challenge.find(10) rescue nil
Hallgeir Wilhelmsen

31

ใน Rails 4 เครื่องมือค้นหาแบบไดนามิกเช่นfind_by_idที่ใช้ในคำตอบที่ยอมรับได้เลิกใช้งานแล้ว

ในขั้นต่อไปคุณควรใช้ไวยากรณ์ใหม่:

Challenge.find_by id: 10

4
เผื่อว่าคนอื่นจะสับสนเหมือนฉัน: Challenge.find_by(id: 10)เป็นวิธีอื่นในการเขียน
Devin Howard

14

คุณสามารถทำสิ่งนี้ได้เล็กน้อยเพียงแค่ใช้ ActiveRecord Query Interface

สิ่งนี้จะคืนค่าศูนย์แทนที่จะเพิ่มข้อยกเว้น

  User.where(:id => 10).first

เหตุผลที่ต้องใช้สิ่งนี้แทนที่จะfind_by_idเป็นแบบพกพาจาก Rails 3 ถึง 4 ในราง 4 find_by(:id => 10)นั่นเอง
ยีน

4

คุณสามารถลองสิ่งนี้ Challenge.exists?(10)


7
จะเป็นคำขอพิเศษของ sql
fl00r

ถึงอย่างนั้นฉันคิดว่านี่เป็นการทดสอบที่ดีกว่า
SomeSchmo

ใช้หากคุณไม่สนใจเกี่ยวกับมูลค่าที่ส่งคืน แต่เกี่ยวกับการมีอยู่ของบันทึกใน DB เท่านั้น
Filip Bartuzi

4

ทำไมคุณไม่จับข้อยกเว้น? กรณีของคุณดูเหมือนว่ามีข้อยกเว้นอะไรบ้าง:

begin
  user = User.find(10)
rescue ActiveRecord::RecordNotFound
  puts "some error msg"
end

หากคุณต้องการกู้คืนจากข้อผิดพลาดในบล็อกการช่วยเหลือ (เช่นโดยการตั้งค่าผู้ใช้ตัวยึดตำแหน่ง (รูปแบบ null)) คุณสามารถดำเนินการต่อโดยใช้รหัสของคุณด้านล่างบล็อกนี้ ไม่เช่นนั้นคุณอาจใส่รหัสทั้งหมดของคุณสำหรับ "happy case" ในบล็อกระหว่าง "begin" และ "rescue"


Btw: คุณไม่จำเป็นต้องใช้begin…endบล็อกถ้าคุณมีบล็อกเช่นวิธีการควบคุม ในกรณีนั้นคุณต้องมีบรรทัดพิเศษเพียงเส้นrescueเดียว หรูหราและจัดการง่ายกว่าการตรวจสอบnilด้วยifคำสั่ง
พนักงานเก็บศพ

4

สำหรับผู้ที่กำลังดิ้นรนกับmongoidปรากฎว่าทั้งสองวิธีfindและfind_byวิธีการต่างๆจะทำให้เกิดข้อยกเว้นไม่ว่าคุณจะใช้รางรุ่นใดก็ตาม!

มีตัวเลือก (เช่นRaise_not_found_error ) ซึ่งสามารถตั้งค่าเป็นเท็จได้ แต่เมื่อสร้างfindเมธอดfalse ก็จะไม่เพิ่มข้อยกเว้นเช่นกัน

ดังนั้นวิธีแก้ปัญหาสำหรับผู้ใช้ mongoid จึงเป็นรหัสที่น่ารังเกียจ:

User.where(id: 'your_id').first # argghhh

คุณคิดอย่างไรกับวิธีการช่วยเหลือโดย Mohamed-ibrahim? ดูสง่างามกว่า.where(email: params[:email]).firstสำหรับฉัน
Wylliam Judd

1
ฉันไม่อยากใช้rescueไวยากรณ์นั้นเพราะมันสามารถซ่อนปัญหาเช่นการพิมพ์ผิด
Cristiano Mendonça

ฉันใช้วิธีแก้ปัญหาของ @ morgler
Wylliam Judd

2

ง่ายๆเพียงแค่:

user = User.find(10) rescue nil

1
ฉันค่อนข้างจะเจาะจงมากขึ้นเกี่ยวกับข้อผิดพลาดที่คาดว่าจะได้รับการช่วยเหลือในกรณีนี้ ActiveRecord :: RecordNotFound ตามที่ระบุไว้ในคำตอบนี้โดย @morgler
luizrogeriocn

2
ฉันเองพบว่านี่เป็นคำตอบที่ดีที่สุด ฉันบอกรหัสของฉันอยู่แล้วว่าจะทำอย่างไรถ้าไม่พบผู้ใช้ในif user...else
Wylliam Judd

0

คุณสามารถใช้ find_by กับแอตทริบิวต์ที่ต้องการ (ในกรณีของคุณคือ id) ซึ่งจะส่งคืนค่า nil แทนที่จะให้ข้อผิดพลาดหากไม่พบ id ที่ระบุ

user = Challenge.find_by_id(id_value)

หรือคุณสามารถใช้รูปแบบใหม่:

user = Challenge.find_by id: id_value

คุณยังสามารถใช้ที่ไหนก็ได้ แต่คุณต้องรู้ว่าที่ที่ส่งคืนความสัมพันธ์ของเรกคอร์ดที่ใช้งานอยู่โดยมีระเบียนศูนย์หรือมากกว่านั้นคุณต้องใช้ก่อนเพื่อส่งคืนระเบียนเดียวหรือศูนย์ในกรณีที่ระเบียนศูนย์ส่งกลับ

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