दिलचस्प पोस्ट
कैसे NSArray और NSDictionary के लिए सही गहरी प्रतिलिपि बनाने के लिए नेस्टेड एरेज़ / डिक्शनरी है? LINQ से एसक्यूएल और क्रमबद्ध परिणामों पर चलने वाला कुल डेटाबेस तालिका में क्रमबद्ध क्रम कॉलम का उपयोग करना एक HTML तत्व की स्थिति (एक्स, वाई) पुनर्प्राप्त करें क्या मैं जनरेटर के साथ ES6 के तीर फ़ंक्शन सिंटैक्स का उपयोग कर सकता हूं? (तीर नोटेशन) यू '\ ufeff' पायथन स्ट्रिंग में क्लासपाथ में कहीं से संसाधन लोड करें Google नक्शे v3 में बहुभुज का केंद्र कैसे प्राप्त करें? जांचें कि तालिका मौजूद है या नहीं रनटाइम पर भाषा बदलने का सही तरीका क्या परिस्थितियों में WPF ऑब्जेक्ट ठंड प्रदर्शन बहुत लाभ? पार्सर त्रुटि संदेश: 'TestMvcApplication.MvcApplication' प्रकार लोड नहीं किया जा सका HTTP पोस्ट वेब अनुरोध कैसे करें एंड्रॉइड: चेकबॉक्स का सेट रंग java.net.SocketException: कनेक्शन रीसेट करें

क्या नेस्टेड पैराम्स हैश में शून्य पर कोई विधि कॉल करने से बचने का एक साफ तरीका है?

मुझे पैरामेसन हैश के नेस्टेड 'नाम' पैरामीटर प्राप्त करने में दिलचस्पी है जैसे कुछ कॉलिंग

params[:subject][:name] 

पैरामीटर [: विषय] खाली है जब एक त्रुटि फेंकता इस त्रुटि से बचने के लिए मैं आमतौर पर ऐसा कुछ लिखता हूं:

 if params[:subject] && params[:subject][:name] 

क्या यह लागू करने का एक क्लीनर तरीका है?

वेब के समाधान से एकत्रित समाधान "क्या नेस्टेड पैराम्स हैश में शून्य पर कोई विधि कॉल करने से बचने का एक साफ तरीका है?"

जांचें Ick शायद हो सकता है आपको अपने कोड को महत्वपूर्ण ढंग से रिफ्लेक्टर करने की आवश्यकता नहीं है, बस आवश्यक होने पर शायद प्रॉक्सी को घुसाना संभव है:

 params[:subject].maybe[:name] 

उसी लेखक ( रेगनवॉल्ड ) ने भी इसी विचार से और भी लिखा था।

  1. आप #try उपयोग कर सकते हैं, लेकिन मुझे नहीं लगता कि यह बहुत बेहतर है:

     params[:subject].try(:[], :name) 
  2. या डिफ़ॉल्ट पैरामीटर के साथ #fetch उपयोग करें:

     params.fetch(:subject, {}).fetch(:name, nil) 
  3. या आप #default= को नए खाली हैश पर सेट कर सकते हैं, लेकिन फिर इस से लौटाए गए मानों को संशोधित करने का प्रयास न करें:

     params.default = {} params[:subject][:name] 

    यह अस्तित्व के लिए सभी साधारण परीक्षणों को तोड़ता है, ताकि आप यह नहीं लिख सकें:

     if params[:subject] 

    क्योंकि यह खाली हैश लौटाएगा, अब आपको #present? जोड़ना #present? हर परीक्षा के लिए कॉल करें

    इसके अलावा यह हमेशा हैश देता है जब कुंजी के लिए कोई मूल्य नहीं होता है, तब भी जब आप स्ट्रिंग की अपेक्षा करते हैं

लेकिन जो मैं देखता हूं, आप इसे मॉडल के लिए निर्दिष्ट करने के बजाय नेस्टेड पैरामीटर निकालने का प्रयास करते हैं और वहां आपके तर्क रखता है। यदि आपके पास Subject मॉडल है, तो बस असाइन करना:

 @subject = Subject.new(params[:subject]) 

अपने सभी मापदंडों को प्रपत्र में भरे हुए उपयोगकर्ताओं को निकालें। फिर आप उन्हें सहेजने की कोशिश करते हैं, यह देखने के लिए कि उपयोगकर्ता वैध मानों को पार कर गया है या नहीं।

यदि आप उस फ़ील्ड को एक्सेस करने के बारे में चिंतित हैं जो उपयोगकर्ता को सेट नहीं करना चाहिए, तो फ़ील्ड के लिए attr_accessible श्वेतसूची जोड़ें, attr_accessible भौतिक असाइनमेंट के साथ सेट करने की अनुमति दी जानी चाहिए (मेरे उदाहरण के रूप में, @subject.attributes = params[:subject] के साथ @subject.attributes = params[:subject] अद्यतन @subject.attributes = params[:subject] अद्यतन के लिए)

रूबी 2.3.0 यह #डीआईजी के साथ करना बहुत आसान बनाता है

 h = {foo: {bar: {baz: 1}}} h.dig(:foo, :bar, :baz) #=> 1 h.dig(:foo, :zot, :baz) #=> nil 

params[:subject].try(:[], :name) सबसे स्वच्छ तरीका है

जब मुझे कोडिंग में एक ही समस्या है, तो मैं कभी-कभी 'बचाव' का उपयोग करता हूं

 name = params[:subject][:name] rescue "" # => "" 

यह अच्छा व्यवहार नहीं है, लेकिन मुझे लगता है कि यह आसान तरीका है।

संपादित करें: मैं इस तरह से अक्सर उपयोग नहीं करते मैं try या fetch की सलाह देते हैं

ज़रुरी नहीं। आप fetch या try (ActiveSupport से) की try कर सकते हैं, लेकिन आपके पास पहले से जो कुछ है, उसके मुकाबले यह बहुत क्लीनर नहीं है।

यहां अधिक जानकारी:

  • नेस्टेड हैश परिभाषित? ()

अद्यतन: और के बारे में भूल गए:

andand आपको यह करने की सुविधा देता है:

 params[:user].andand[:name] # nil guard is built-in 

इसी तरह, आप ऊपर दिए गए उत्तर के अनुसार आईक पुस्तकालय से maybe उपयोग कर सकते हैं।

या, इसे [] जोड़ें

 class NilClass; def [](*); nil end end params[:subject][:name] 
 class Hash def fetch2(*keys) keys.inject(self) do |hash, key| hash.fetch(key, Hash.new) end end end 

जैसे

 require 'minitest/autorun' describe Hash do it "#fetch2" do { yo: :lo }.fetch2(:yo).must_equal :lo { yo: { lo: :mo } }.fetch2(:yo, :lo).must_equal :mo end end 

मैं यहां अपने उत्तर से यह पोस्ट किया है:

जांच कैसे करें कि क्या पैरामांज़ [: कुछ] [: फ़ील्ड] शून्य है?

मैं एक बेहतर समाधान की तलाश भी कर रहा हूं

इसलिए मैंने सोचा था कि नेस्टेड कुंजी सेट होने के लिए परीक्षण करने के लिए एक अलग तरीके का उपयोग try :

 params[:some].try(:has_key?, :field) 

यह बुरा नहीं है। यदि nil सेट नहीं है तो आपको nil बनाम false मिलता है। आप true भी हो सकते true यदि परम nil से तय है

मैंने डॉटि को सिर्फ इस उपयोग के मामले के लिए लिखा था – पहले पता नहीं था कि पूरे अपेक्षित पेड़ मौजूद है, बिना एक हैश में गहरे तक पहुंचने के लिए। वाक्यविन्यास try (रेल) या maybe (Ick) की तुलना में अधिक संक्षिप्त है उदाहरण के लिए:

 # in a Rails request, assuming `params` contains: { 'person' => { 'email' => 'jon@example.com' } } # there is no 'subject' # standard hash access (symbols will work here # because params is a HashWithIndifferentAccess) params[:person][:email] # => 'jon@example.com' params[:subject][:name] # undefined method `[]' for nil:NilClass # with Dottie Dottie(params)['person.email'] # => 'jon@example.com' Dottie(params)['subject.name'] # => nil # with Dottie's optional class extensions loaded, this is even easier dp = params.dottie dp['person.email'] # => 'jon@example.com' dp['subject.name'] # => nil dp['some.other.deeply.nested.key'] # => nil 

यदि आप अधिक देखना चाहते हैं तो डॉक्स देखें: https://github.com/nickpearson/dottie

मैंनें इस्तेमाल किया:

 params = {:subject => {:name => "Jack", :actions => {:peaceful => "use internet"}}} def extract_params(params, param_chain) param_chain.inject(params){|r,e| r=((r.class.ancestors.include?(Hash)) ? r[e] : nil)} end extract_params(params, [:subject,:name]) extract_params(params, [:subject,:actions,:peaceful]) extract_params(params, [:subject,:actions,:foo,:bar,:baz,:qux]) 

देता है:

 => "Jack" => "use internet" => nil 

आप एक इनलाइन असाइनमेंट के साथ डबल हैश एक्सेस से बच सकते हैं:

 my_param = subj_params = params[:subject] && subj_params[:name]