ตรวจสอบว่ามีบันทึกจากคอนโทรลเลอร์ใน Rails หรือไม่


92

ในแอปของฉันผู้ใช้สามารถสร้างธุรกิจได้ เมื่อพวกเขาทริกเกอร์การindexดำเนินการในของBusinessesControllerฉันฉันต้องการตรวจสอบว่าธุรกิจเกี่ยวข้องกับcurrent_user.id:

  • ถ้าใช่: แสดงธุรกิจ
  • ถ้าไม่: เปลี่ยนเส้นทางไปที่newการดำเนินการ

ฉันพยายามใช้สิ่งนี้:

if Business.where(:user_id => current_user.id) == nil
  # no business found
end

แต่มันกลับเป็นจริงเสมอแม้ธุรกิจจะไม่มี ...

ฉันจะทดสอบได้อย่างไรว่ามีระเบียนอยู่ในฐานข้อมูลของฉันหรือไม่


1
การใช้whereจะส่งคืนอาร์เรย์ว่างหากไม่มีเรกคอร์ด และ[]ไม่เท่ากันnil
mind.blank

แล้วแค่ a unless Business.find_by_user_id(current_user.id)?
Hengjie

คำตอบ:


234

ทำไมรหัสของคุณไม่ทำงาน

whereวิธีการส่งกลับActiveRecord :: สัมพันธ์วัตถุ (ทำหน้าที่เหมือนอาร์เรย์ที่มีผลของwhere) ก็สามารถเป็นที่ว่างเปล่า nilแต่มันจะไม่เป็น

Business.where(id: -1) 
 #=> returns an empty ActiveRecord::Relation ( similar to an array )
Business.where(id: -1).nil? # ( similar to == nil? )
 #=> returns false
Business.where(id: -1).empty? # test if the array is empty ( similar to .blank? )
 #=> returns true

จะทดสอบได้อย่างไรว่ามีอย่างน้อยหนึ่งรายการหรือไม่?

ตัวเลือกที่ 1:การใช้.exists?

if Business.exists?(user_id: current_user.id)
  # same as Business.where(user_id: current_user.id).exists?
  # ...
else
  # ...
end

ตัวเลือกที่ 2:การใช้.present?(หรือ.blank?ตรงกันข้ามกับ.present?)

if Business.where(:user_id => current_user.id).present?
  # less efficiant than using .exists? (see generated SQL for .exists? vs .present?)
else
  # ...
end

ตัวเลือกที่ 3: การกำหนดตัวแปรในคำสั่ง if

if business = Business.where(:user_id => current_user.id).first
  business.do_some_stuff
else
  # do something else
end

ตัวเลือกนี้ถือได้ว่าเป็นกลิ่นรหัสจากเศษผ้าบางชนิด (เช่น Rubocop)

ตัวเลือก 3b:การกำหนดตัวแปร

business = Business.where(user_id: current_user.id).first
if business
  # ...
else
  # ...
end

คุณยังสามารถใช้.find_by_user_id(current_user.id)แทนไฟล์.where(...).first


ตัวเลือกที่ดีที่สุด:

  • หากคุณไม่ใช้Businessวัตถุ: ตัวเลือกที่ 1
  • หากคุณจำเป็นต้องใช้Businessวัตถุ: ตัวเลือกที่ 3

ดูเหมือนจะไม่ได้ผล มันยังคงผ่านการทดสอบนั้นและโหลด html ของดัชนีเช่นเดียวกับการทดสอบ == nil (ดังนั้นฉันจึงได้รับข้อผิดพลาด: วิธีการที่ไม่ได้กำหนดชื่อสำหรับ nil: NilClass)

ลองใช้ก่อนโทรหาของขวัญ
MrYoshiji

โอ้นั่นเป็นความผิดของฉันฉันสับสนคุณต้องทดสอบด้วยblank?
MrYoshiji

ขอบคุณที่ทำงาน! ฉันไม่ควรสังเกตเห็นความผิดพลาดนั้น คุณช่วยบอกฉันได้ไหมว่าทำไมการตรวจสอบ == ไม่ทำงาน

ใช่ให้เวลาฉันสักครู่ฉันจะอัปเดตคำตอบของฉันและไม่ใช้.firstก่อนหน้า.blank?นี้)
MrYoshiji

29

ในกรณีนี้ฉันต้องการใช้exists?วิธีการที่ ActiveRecord ให้ไว้:

Business.exists? user_id: current_user.id

มีอยู่จริง? ด้วยหรือเป็นไปได้?
Imran Ahmad

5

ด้วย 'มีอยู่?':

Business.exists? user_id: current_user.id #=> 1 or nil

ด้วย 'any?':

Business.where(:user_id => current_user.id).any? #=> true or false

หากคุณใช้บางอย่างกับ. ที่ไหนอย่าลืมหลีกเลี่ยงปัญหาเกี่ยวกับขอบเขตและใช้. unscoped ให้ดีขึ้น

Business.unscoped.where(:user_id => current_user.id).any?

ใช้ Business.unscoped.where ดีกว่า (: user_id => current_user.id) .pluck (: id) .any? เพื่อหลีกเลี่ยงความสัมพันธ์ที่ไม่จำเป็นสำหรับวัตถุที่คุณกำลังตรวจสอบ
Juanin

1

ActiveRecord # ซึ่งจะส่งคืนอ็อบเจ็กต์ ActiveRecord :: Relation (ซึ่งจะไม่เป็นศูนย์) ลองใช้. ว่างไหม เกี่ยวกับความสัมพันธ์เพื่อทดสอบว่าจะส่งคืนระเบียนใด ๆ


1

เมื่อคุณโทรBusiness.where(:user_id => current_user.id)คุณจะได้รับอาร์เรย์ Array นี้อาจไม่มีวัตถุหรือวัตถุหนึ่งชิ้นหรือหลายชิ้นอยู่ในนั้น แต่จะไม่เป็นโมฆะ ดังนั้นการตรวจสอบ == ศูนย์จะไม่เป็นจริง

คุณสามารถลองทำสิ่งต่อไปนี้:

if Business.where(:user_id => current_user.id).count == 0

ดังนั้นคุณจึงตรวจสอบจำนวนองค์ประกอบในอาร์เรย์และเปรียบเทียบกับศูนย์

หรือคุณสามารถลอง:

if Business.find_by_user_id(current_user.id).nil?

สิ่งนี้จะคืนค่าหนึ่งหรือศูนย์



0

ฉันจะทำแบบนี้ถ้าคุณต้องการตัวแปรอินสแตนซ์ของออบเจ็กต์ที่จะใช้งานได้:

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.