मुझे 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 जैसा कुछ चाहता हूं, एक "या फिर" के साथ।
रेल्स संग्रह रेंडर करना
आपके व्यूज़ के अंदर, रेल्स मदद कर सकता है। यह चीजों के संग्रह को रेंडर करने में बहुत अच्छा है:
<%= 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>
एक बार जब आप रेल्स के कन्वेंशन्स को समझ लेते हैं, तो यह बहुत अधिक सीधा है।
व्यू के बाहर क्या?
यदि आप रेल्स का पालन करते हैं, तो संग्रह के साथ 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.")
या स्मॉलटॉक-ईश:
@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 पैटर्न के साथ जाता हूं।
आपको क्या लगता है कि बेहतर है? आप खाली सूचियों को कैसे संभालते हैं? क्या आपको कोई बेहतर तरीका मिला है? यदि हां, तो मुझे इसके बारे में बताएं!