มี Ruby หรือ Ruby-ism สำหรับ not_nil? ตรงข้ามกับศูนย์? วิธี?


87

ฉันไม่มีประสบการณ์ใน Ruby ดังนั้นรหัสของฉันจึงรู้สึก "น่าเกลียด" และไม่ใช่สำนวน:

def logged_in?
  !user.nil?
end

ฉันอยากจะมีสิ่งที่ชอบ

def logged_in?
  user.not_nil?
end

แต่ไม่พบวิธีการดังกล่าวที่ตรงข้าม nil?

คำตอบ:


50

เมื่อคุณใช้ ActiveSupport มีuser.present? http://api.rubyonrails.org/classes/Object.html#method-i-present%3Fเพื่อตรวจสอบว่าไม่ใช่ศูนย์ทำไมไม่ใช้

def logged_in?
  user # or !!user if you really want boolean's
end

48
ระวัง: present?ต้องใช้สตริงที่ไม่ว่างเปล่า ! "".nil?คืนค่าจริง แต่"".present?ส่งกลับเท็จ
lambshaanxy

9
ระวัง 2: ฉันจะสังเกตด้วยว่า !! ผู้ใช้ไม่ได้แยกความแตกต่างระหว่างผู้ใช้ที่เป็นศูนย์และผู้ใช้เป็นเท็จ การใช้งานดับเบิ้ลปังทำให้สองคนนั้นรวมกัน ดังนั้นหากคุณต้องการตรวจสอบว่าวัตถุนั้นไม่ใช่ศูนย์อย่างแท้จริง (ความหมายคือ: จริงเท็จ 0 "" สิ่งอื่นใดที่ไม่ใช่ศูนย์) คุณต้องใช้วิธี 'น่าเกลียด' ที่เบอร์คไม่ชอบ หรือ monkeypatch ที่ @Tempus เสนอดังต่อไปนี้ แน่นอนในกรณีนี้ที่ไม่ได้ศูนย์จะไม่จำเป็น (ผู้ใช้ใน Rails) วิธีการดำเนินการโดยสมอเป็นที่น่าเกลียดน้อย IMO
likethesky

12
false.present? == false !false.nil? == true
Dudo

3
คำตอบนี้ไม่ได้ตอบคำถามที่ถามเลย เป็นคำตอบสำหรับปัญหาการใช้งานนี้โดยเฉพาะ
Ekkstein

3
คำตอบนี้ไม่ถูกต้อง false.nil? เป็นเท็จในขณะที่ false.present? ยังเป็นเท็จ!
Mike

49

ดูเหมือนคุณจะกังวลกับบูลีนมากเกินไป

def logged_in?
  user
end

หากผู้ใช้เป็นศูนย์แล้ว logged_in? จะส่งคืนค่า "falsey" มิฉะนั้นจะส่งคืนวัตถุ ใน Ruby เราไม่จำเป็นต้องส่งคืนจริงหรือเท็จเนื่องจากเรามีค่า "จริง" และ "เท็จ" เหมือนใน JavaScript

อัปเดต

หากคุณใช้ Rails คุณสามารถทำให้สิ่งนี้อ่านได้ดีขึ้นโดยใช้present?วิธีการ:

def logged_in?
  user.present?
end

1
ความคาดหวังด้วยเมธอดที่ลงท้ายด้วย a ?คือมันส่งคืนบูลีน !!valueเป็นวิธีคลาสสิกในการแปลงอะไรเป็นบูลีน ไม่เหมือนกันObject#present?ทุกประการแต่ในกรณีนี้ใน RoR ก็ดีเช่นกัน
tokland

สิ่งนี้แตกจริงใน Ruby 2.4 ด้วย Path! [43] (แงะ) # <ReactOnRails :: AssetsPrecompile>: 0> assets_path.blank? จริง [44] (แงะ) # <ReactOnRails :: AssetsPrecompile>: 0> assets_path.to_s "/ var / โฟลเดอร์ / rp / _k99k0pn0rsb4d3lm9l3dnjh0000gn / T / d20170603-96466-zk7di7" [45] (แงะ) # <ReactOile >: 0> assets_path.present? เท็จ [46] (แงะ) # <ReactOnRails :: AssetsPrecompile>: 0> assets_path.nil? เท็จ
justingordon

26

ระวังคำตอบอื่น ๆ ที่นำเสนอ present?ที่เป็นคำตอบสำหรับคำถามของคุณ

present? ตรงกันข้ามกับ blank?ในราง

present?ตรวจสอบว่ามีค่าที่มีความหมายหรือไม่ สิ่งเหล่านี้อาจทำให้การpresent?ตรวจสอบล้มเหลว:

"".present? # false
"    ".present? # false
[].present? # false
false.present? # false
YourActiveRecordModel.where("false = true").present? # false

ในขณะที่!nil?เช็คให้:

!"".nil? # true
!"    ".nil? # true
![].nil? # true
!false.nil? # true
!YourActiveRecordModel.where("false = true").nil? # true

nil?ตรวจสอบว่ามีวัตถุอยู่จริงnilหรือไม่ อย่างอื่น: สตริงว่าง0,falsenilสิ่งที่ไม่ได้เป็น

present? มีประโยชน์มาก แต่ไม่ตรงกันข้ามกับ nil? . การสับสนทั้งสองอย่างอาจนำไปสู่ข้อผิดพลาดที่ไม่คาดคิด

สำหรับกรณีการใช้งานของคุณจะใช้present?งานได้ แต่ควรตระหนักถึงความแตกต่างอยู่เสมอ


ควรรวมอยู่ในคำตอบที่ยอมรับ false.blank?ไม่เหมือนกับfalse.nil?
Yason

present?จะค้นหาฐานข้อมูลของคุณnil?จะไม่ระวังด้วย
Tony

17

บางทีนี่อาจเป็นแนวทาง:

class Object
  def not_nil?
    !nil?
  end
end

ความคิดที่ดี. ฉันทำจากสิ่งนี้ว่าไม่มี not_nil? ใน Ruby แต่นี่ไม่ควรจะ!self.nil?เป็นอย่างนั้น!nil?หรือselfโดยปริยาย?
Berkes

3
คุณไม่ต้องการตัวเอง มันจะบอกเป็นนัย ๆ
Geo

โดยนัยเมื่ออ่านจากวิธีการอินสแตนซ์ (หรือตัวเข้าถึงซึ่งเป็นเพียงวิธีการเท่านั้น) เมื่อตั้งค่าตัวแปรโลคัลให้กับเมธอดจะถูกสร้างขึ้นก่อนที่ Ruby จะตรวจสอบอินสแตนซ์คลาสเพื่อหาเมธอด setter ที่มีชื่อเดียวกัน กฎทั่วไป: หากคุณมี attr_accessor ชื่อ xxx ให้ใช้ "self.xxx = 3" (การตั้งค่า) หรือ "temp = xxx" (การอ่านค่า) การใช้ "xxx = 3" จะไม่อัปเดตตัวเข้าถึงเพียงแค่สร้างตัวแปรใหม่ในขอบเขตวิธีการ
A Fader Darkly

5

ฉันขอเสนอวิธี Ruby-esque !เกี่ยวกับผลลัพธ์จากnil?วิธีการ

def logged_in?
  user.nil?.!
end

เป็นความลับที่ RubyMine IDE จะตั้งค่าสถานะเป็นข้อผิดพลาด ;-)


4

คุณสามารถใช้สิ่งต่อไปนี้:

if object
  p "object exists"
else
  p "object does not exist"
end

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


2

ฉันมาถึงคำถามนี้โดยมองหาวิธีวัตถุเพื่อที่ฉันจะได้ใช้Symbol#to_procชวเลขแทนการบล็อก ผมพบว่าค่อนข้างอ่านได้มากขึ้นกว่าarr.find(&:not_nil?)arr.find { |e| !e.nil? }

วิธีที่ฉันพบคือObject#itself. ในการใช้งานของฉันฉันต้องการที่จะหาค่าในกัญชาสำหรับคีย์ซึ่งในบางกรณีที่สำคัญได้รับทุนบังเอิญเป็นname Nameซับเดียวนั้นมีดังนี้:

# Extract values for several possible keys 
#   and find the first non-nil one
["Name", "name"].map { |k| my_hash[k] }.find(&:itself)

ดังที่ระบุไว้ในคำตอบอื่น ๆสิ่งนี้จะล้มเหลวอย่างไม่น่าเชื่อในกรณีที่คุณกำลังทดสอบบูลีน


แตกต่างจากmy_hash.values_at("Name", "name").findอย่างไร?
Berkes

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