ฉันชอบ each
แต่ฉันมีปัญหากับมัน จะเกิดอะไรขึ้นเมื่อคุณมีคอลเล็กชันที่ว่างเปล่า
หากคุณเรียก [].each
จะไม่มีอะไรเกิดขึ้นและ []
จะถูกส่งกลับ บางครั้งนั่นคือสิ่งที่คุณต้องการ แต่บ่อยครั้งกว่านั้น โดยเฉพาะอย่างยิ่งเมื่อคุณสร้าง UI คุณจะต้องจัดการรายการว่างด้วยวิธีพิเศษ เช่น ฉันมักจะต้องการแสดงข้อความอื่นเมื่อไม่มีข้อมูล
แต่เนื่องจาก [].each
ส่งกลับ []
ไม่ใช่ nil
คุณกำลังเขียนสิ่งนี้อยู่:
<% if @users.empty? -%>
<p>You don't have any users. <%= link_to "Add one!", new_user_path %></p>
<% else -%>
<% @users.each do |user| -%>
<p><%= user.name %></p>
<% end -%>
<% end -%>
ใช้งานได้ แต่รู้สึกอึดอัด ฉันอยากจะพูดว่า "ทำสิ่งนี้กับแต่ละรายการในคอลเล็กชันนี้ เว้นแต่จะไม่มีอะไรอยู่ในนั้น ในกรณีนี้ให้ทำอย่างอื่นทั้งหมด" ฉันต้องการบางอย่างเช่น each
ด้วย “หรืออย่างอื่น”
Rendering Rails Collections
ในมุมมองของคุณ Rails ช่วยคุณได้ การแสดงคอลเลกชั่นของสิ่งต่าง ๆ นั้นยอดเยี่ยม:
<%= render @users %>
<p><%= user.name %></p>
เมื่อ render
ถูกส่งผ่าน @users
มันแสดงผล _user.html.erb
หนึ่งครั้งสำหรับผู้ใช้แต่ละคนใน @users
. คุณสามารถข้าม each
โดยสิ้นเชิง
เป็นโบนัส ถ้า @users
ว่างเปล่า render
คืนค่า nil
อย่างที่เราต้องการ! ดังนั้นคุณจึงสามารถเขียนสิ่งนี้ และรับผลลัพธ์เหมือนกับเวอร์ชันดั้งเดิม:
<%= render(@users) || render('empty') %>
<p><%= user.name %></p>
<p>You don't have any users. <%= link_to "Add one!", new_user_path %></p>
ตรงไปตรงมามากขึ้น เมื่อคุณเข้าใจแบบแผนของ Rails แล้ว
สิ่งที่อยู่นอกมุมมองคืออะไร
หากคุณติดตาม Rails render
ด้วยคอลเล็กชันเป็นวิธีที่รวดเร็วและมีประสิทธิภาพในการแสดงคอลเล็กชันของออบเจ็กต์
แต่บางครั้งคุณอาจไม่ต้องการจัดการกับส่วนเพิ่มเติมในการแสดงผลแต่ละรายการ หรือ render
จะไม่สนับสนุนการออกแบบของคุณ หรือคุณจะไม่อยู่ในมุมมองด้วยซ้ำ
ทางออกที่ดีที่สุดที่ฉันพบคือ presence
.
list.presence
เหมือนกับ:
if list.present?
list
else
nil
end
นั่นคือ คุณจะได้รับรายการกลับมาหากมีอะไรอยู่ในนั้น และ nil
ถ้าว่าง
ด้วย presence
, คุณสามารถเขียน:
@users.each do |user|
puts user.name
end.presence || puts("You don't have any users.")
สิ่งนี้จะพิมพ์ชื่อแต่ละชื่อหากมีผู้ใช้ใน @users
หรือ You don't have any users
อย่างอื่น
ถึงกระนั้นฉันก็ทำได้โดยไม่มี presence
. รู้สึกเหมือนแฮ็คเพราะมันเป็นหนึ่ง หากได้รับการสนับสนุน สิ่งที่ดีกว่านี้:
@users.each do |user|
puts user.name
end || puts("You don't have any users.")
หรือ Smalltalk-ish:
@users.each(if_empty: lambda { puts "You don't have any users." }) do |user|
puts user.name
end
หรือแม้กระทั่ง (อ้าปากค้าง!):
for user in @users
puts user.name
else
puts "You don't have any users."
end
แต่สำหรับตอนนี้ฉันมักจะไปกับ presence
หรือ if blank?; else each
รูปแบบ
คุณคิดว่าแบบไหนดีกว่ากัน? คุณจัดการกับรายการว่างได้อย่างไร? คุณพบวิธีที่ดีกว่าหรือไม่? ถ้าเป็นเช่นนั้นบอกฉัน!