2010-08-21 12 views
5

मुझे यकीन है कि यह पहले से ही पूछा गया है, लेकिन मुझे जवाब नहीं मिला।रेल दृश्यों में शून्य से बचें

मेरे पास एक प्रोजेक्ट मॉडल है, जिसमें मेरे क्लाइंट मॉडल के साथ belongs_to संबंध है। एक ग्राहक का नाम होता है, लेकिन एक प्रोजेक्ट में क्लाइंट की आवश्यकता नहीं होती है।

मेरी नजर में, मैं इस तरह कोड मिल गया है:

<%=h project.client && project.client.name %> 

क्योंकि अगर परियोजना एक ग्राहक नहीं है तो project.client.name एक्सेस करते समय NoMethodError (nil का कारण बनता है एक विधि कहा जाता है नहीं है name)।

सवाल यह है कि क्या इस तरह की नील जांच को देखने में स्वीकार्य है, या क्या मुझे इसके चारों ओर एक और तरीके की तलाश करनी चाहिए?

उत्तर

10

बस का उपयोग

project.client.try(:name) 
+0

मैं उसे भूल गया ... :) हालांकि, जब भी आप 5-6 मॉडल गहरे नीचे जा रहे हैं तो यह अभी भी बोझिल हो जाता है। :( – DGM

+3

http://en.wikipedia.org/wiki/Law_of_Demeter – Reactormonk

+0

@ टास आप डेमेटर के कानून के बारे में सही हैं, लेकिन मुझे लगता है कि इसे लागू करने का सही तरीका नहीं है, कृपया नीचे मेरी पोस्ट देखें। – dombesz

3

मुझे लगता है कि यह पूरी तरह से स्वीकार्य है - यह तर्क तर्क है, आप डेटा के आधार पर आपके विचार के भाग दिखाने के लिए या अधिक निर्णय ले रहे हैं या नहीं।

3

मैं हर समय इसमें दौड़ता हूं, और हाँ यह कष्टप्रद है। यहां तक ​​कि जब कभी भी शून्य न हो, तब भी गंदे डेटा जो मैंने विरासत में प्राप्त किया है, कभी-कभी इसे ट्रिगर करता है।

आपका समाधान इसे संभालने का एक तरीका है। आप Project पर client_name नामक एक विधि भी जोड़ सकते हैं जो क्लाइंट नाम प्रदर्शित करता है यदि यह मौजूद है, लेकिन फिर आप कुछ लोगों की सिफारिशों के मुकाबले मॉडलों को एक साथ जोड़ रहे हैं।

def client_name 
    client && client.name 
end 

आप इसे करने के लिए एक सहायक विधि भी बना सकते हैं, लेकिन आप उनमें से बहुत कुछ लिख सकते हैं। :)

नीचे Skilldrick से उल्लेख किया है, यह भी उपयोगी एक डिफ़ॉल्ट स्ट्रिंग को जोड़ने के लिए है:

def client_name 
    client ? client.name : "no client" 
end 
+1

में delegate बारे में अधिक देखें यह निश्चित रूप से है कुछ परिस्थितियों में उपयोगी (उदाहरण के लिए यदि आप "नो क्लाइंट" जैसे डिफ़ॉल्ट नाम चाहते हैं)। – Skilldrick

+1

टर्नरी ऑपरेटर का उपयोग किए बिना एक और डिफ़ॉल्ट स्ट्रिंग कार्यान्वयन: 'client.name || "कोई ग्राहक नहीं" ' – Eric

+0

कोई भी तर्क दे सकता है कि, मूल प्रश्न एक शुद्ध एमवीसी मॉडल होने पर चर्चा कर रहा था, कि आपके मॉडल में एक डिफ़ॉल्ट डिस्प्ले स्ट्रिंग डालने से, आप इंजेक्शन कर सकते हैं कि वास्तव में आपके मॉडल में तर्क क्या है, नहीं? यही कारण है कि मैंने इसे प्रश्नकर्ता द्वारा किया था। लेकिन, यह सभी शैली है, यह भी काम करता है :)। मुझे यह मानने से नफरत है कि मैंने जो भी देखा है, मैं वही डिफ़ॉल्ट स्ट्रिंग चाहता हूं, आपको पता है? – jasonpgignac

0

मेरी hacky समाधान एक ब्लॉक उपज के लिए है और त्रुटि को बचाने के । कई लोग बचाव का उपयोग कर कहते हैं क्योंकि तर्क बहुत खराब रूप है। बस इसका उपयोग न करें जहां आपको वास्तव में जानना होगा कि कुछ शून्य क्यों है और नहीं होना चाहिए।

application_helper.rb में:

def none_on_fail 
     begin 
      return yield 
     rescue 
      return "(none entered)" 
     end 
    end 
तब ध्यान में रखते हुए

:

<%= none_on_fail { project.client.name } %> 

रूप में की जरूरत है और यह किसी भी विधि पर इस्तेमाल किया जा सकता है लेकिन यह को कवर किया जाएगा तब तरीके के रूप में गहरी श्रृंखलित किया जा सकता है यदि वे मौजूद हैं तो मॉडल/रिश्तों/विधियों के साथ अन्य संभावित समस्याएं। मैं इसे एक flamethrower के साथ एक splinter बाहर लेने के लिए समान होगा। अनुचित तरीके से उपयोग किए जाने पर दर्दनाक परिणामों के साथ बहुत प्रभावी।

+1

बहुत पाइथनिक :) – Skilldrick

0

मुझे लगता है कि ये चेक आमतौर पर थोड़ी सी सोच से समाप्त हो सकते हैं। इसका दृश्य कोड क्लीनर रखने का लाभ है, और अधिक महत्वपूर्ण बात यह है कि व्यू परत से तर्क को ध्यान में रखते हुए, जो एक सर्वोत्तम अभ्यास है। कुछ templating इंजन दृश्य में किसी भी तर्क की अनुमति नहीं है।

कम से कम कुछ परिदृश्य हैं। मान लें कि आपके पास show क्रिया है जो एक आवृत्ति चर पर निर्भर करती है।मैं कहूंगा कि अगर रिकॉर्ड नहीं मिला है तो नियंत्रक को एचटीएमएल को रीडायरेक्ट या कुछ और प्रस्तुत नहीं करना चाहिए। यदि आपके पास सरणी के दृश्य में लूप है, तो @array.each do |a| end का उपयोग करें ताकि यह मूल्यांकन न हो कि सरणी खाली है या नहीं। यदि आप वास्तव में दृश्य में एप्लिकेशन डिफ़ॉल्ट चाहते हैं, तो उसे कॉन्फ़िगरेशन फ़ाइल से लोड करने का प्रयास करें, उदा। @page_title || #{@APP_CONFIG['page_title']} (देखें Railscasts #85)। याद रखें कि आप बाद में इन तारों को बदलना चाहते हैं, उदाहरण के लिए यूआई का अनुवाद करना।

वे कुछ परिदृश्य हैं जहां उपस्थिति की जांच और try का उपयोग टाला जा सकता है। यदि संभव हो तो मैं उनसे बचने की कोशिश करता हूं। यदि आप उनसे नहीं बच सकते हैं, तो मैं सशर्त चेक को एक दृश्य सहायक में रखूंगा और कोड पथ दोनों को सत्यापित करने (और दस्तावेज़) के लिए एक सहायक इकाई परीक्षण जोड़ूंगा।

2

आप अपने Project कक्षा में delegate का उपयोग कर सकते हैं, इस प्रकार आप Law of demeter का सम्मान करेंगे जो कहता है कि आपको "केवल अपने तत्काल मित्रों से बात करनी चाहिए"।

project.rb

class Project 
    delegate :name, to: :client, prefix: true, allow_nil: true  
end 

तो इस तरह से परियोजना वस्तु जहां ग्राहक के नाम के बारे में पूछने के लिए पता चल जाएगा:

#You can now call 
project.client_name 

Rails documentation.

संबंधित मुद्दे