Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

Ruby मॉड्यूल्स को नेस्ट करते समय सामान्य नुकसान से बचें

मॉड्यूल्स (और क्लासेज) को नेस्ट करने के लिए बनाया गया है। ActiveRecord::RecordNotFound जैसे कोड फ्रैगमेंट्स इतने सामान्य हैं कि हम उनके बारे में दो बार नहीं सोचते। लेकिन Ruby के नेस्टिंग इम्प्लीमेंटेशन - और Rails के ऑटोलोड सिस्टम - के भीतर कुछ ट्रैप्स छिपे हुए हैं जो आपके कोड को अजीब और अद्भुत तरीकों से विफल कर सकते हैं। इस पोस्ट में, हम इन ट्रैप्स की उत्पत्ति और उनसे कैसे बचा जाए, इस पर चर्चा करेंगे।

कॉन्स्टेंट क्या है?

यह पोस्ट मॉड्यूल्स के बारे में है, लेकिन उन्हें समझने के लिए हमें कॉन्स्टेंट्स को समझने की आवश्यकता है। अधिकांश भाषाओं में, कॉन्स्टेंट्स का उपयोग केवल डेटा के छोटे टुकड़ों को स्टोर करने के लिए किया जाता है, जैसे नीचे दिए गए उदाहरण में:

# ये सरल कॉन्स्टेंट्स हैं
MAX_RETRIES = 5
DEFAULT_LANGUAGE = "en"

लेकिन Ruby में, क्लासेज और मॉड्यूल्स भी कॉन्स्टेंट्स हैं। मैंने इसे प्रदर्शित करने के लिए एक छोटा उदाहरण लिखा है। नीचे दिए गए मॉड्यूल में तीन कॉन्स्टेंट्स हैं: एक नंबर, एक क्लास और एक नेस्टेड मॉड्यूल। जब आप नेस्टेड क्लास या मॉड्यूल को एक्सेस करते हैं, तो Ruby उसे उन्हीं नियमों का उपयोग करके ढूंढता है जिनका उपयोग वह एक साधारण न्यूमेरिक कॉन्स्टेंट के साथ करेगा।

module MyModule
  MY_FAVORITE_NUMBER = 7
  # क्लासेज कॉन्स्टेंट्स हैं
  class MyClass
  end
  # मॉड्यूल्स भी हैं
  module MyEmbeddedModule
  end
end

puts MyModule.constants.inspect
# => [:MY_FAVORITE_NUMBER, :MyClass, :MyEmbeddedModule]

अक्सर, मॉड्यूल्स को उनके पैरेंट्स में परिभाषित कॉन्स्टेंट्स तक पहुंच होती है। इसलिए आप ऐसा कोड लिख सकते हैं:

module X
  MARCO = "polo"
  module Y
    def self.n
      puts MARCO
    end
  end
end

X::Y.n() # => "polo"

लेकिन आप गलत होंगे यदि आपने सोचा कि यह पैरेंट/चाइल्ड संबंध ही था जो Y को X के कॉन्स्टेंट MARCO तक पहुंचने की अनुमति देता है।

एक सामान्य समस्या

यदि हम उपरोक्त कोड को थोड़े अलग तरीके से लिखते हैं, तो कुछ आश्चर्यजनक होता है। Y अब X::MARCO तक नहीं पहुंच सकता। यहां क्या हो रहा है?

module A
  MARCO = "polo"
end

module A::B
  def self.n
    puts MARCO # => uninitialized constant A::B::MARCO (NameError)
  end
end

A::B.n()

पता चला है कि चाइल्ड द्वारा पैरेंट के कॉन्स्टेंट्स की "विरासत" पैरेंट/चाइल्ड संबंध के कारण नहीं है। यह लेक्सिकल है। इसका मतलब है कि यह आपके कोड की संरचना पर आधारित है, न कि उन ऑब्जेक्ट्स की संरचना पर जो आपका कोड बना रहा है।

नेस्टिंग की जांच

यदि आप यह गहरी समझ चाहते हैं कि Ruby नेस्टेड कॉन्स्टेंट्स की खोज कैसे करता है, तो Module.nesting फंक्शन को देखना उचित है।

यह फंक्शन ऑब्जेक्ट्स की एक सरणी लौटाता है जो दिए गए स्कोप में कॉन्स्टेंट्स के लिए "खोज पथ" बनाते हैं। आइए हमारे पिछले उदाहरणों के लिए नेस्टिंग की जांच करें।

हमारे पहले उदाहरण में, हम देखते हैं कि नेस्टिंग [A::B, A] है। इसका मतलब है कि यदि हम कॉन्स्टेंट MARCO का उपयोग करते हैं, तो Ruby पहले A::B में देखेगा, फिर A में।

module A
  MARCO = "polo"
  module B
    def self.n
      puts Module.nesting.inspect # => [A::B, A]
      puts MARCO # => "polo"
    end
  end
end

दूसरे उदाहरण में, हम देखते हैं कि नेस्टिंग में केवल A::B शामिल है, A नहीं। भले ही B, A का "चाइल्ड" है, लेकिन मैंने कोड को इस तरह लिखा है कि वे नेस्टेड नहीं दिखते, इसलिए इस उद्देश्य के लिए वे ऐसे ही हो सकते हैं जैसे वे नहीं हैं।

module A
  MARCO = "polo"
end

module A::B
  def self.n
    puts Module.nesting.inspect # => [A::B]
    puts MARCO # => uninitialized constant A::B::MARCO (NameError)
  end
end

Rails ऑटोलोड जटिलताएं

क्या आपने कभी ध्यान दिया है कि Rails का उपयोग करते समय आपको फाइल्स को शामिल करने की आवश्यकता नहीं होती? यदि आप एक मॉडल का उपयोग करना चाहते हैं, तो आप बस उसका उपयोग करते हैं।

यह संभव है क्योंकि Rails एक ऑटोलोड सिस्टम लागू करता है। यह Module.const_missing का उपयोग करके पता लगाता है कि आप कब किसी ऐसे कॉन्स्टेंट को संदर्भित करने का प्रयास करते हैं जिसे लोड नहीं किया गया है। फिर यह उन फाइलों को लोड करता है जिनके बारे में उसका मानना है कि उनमें कॉन्स्टेंट होना चाहिए। यह ज्यादातर समय काम करता है, लेकिन एक पकड़ है।

Rails मानता है कि एक मॉड्यूल में हमेशा सबसे बड़ा संभव नेस्टिंग होता है। यह मानता है कि मॉड्यूल A::B::C का नेस्टिंग [A::B::C, A::B, A] होगा। यदि ऐसा नहीं है तो आपको अप्रत्याशित व्यवहार मिलेगा।

नीचे दिए गए कोड में, मॉड्यूल B को A::MARCO तक पहुंचने में सक्षम नहीं होना चाहिए। सामान्य Ruby में, यह सक्षम नहीं होगा क्योंकि इसका नेस्टिंग [A::B] है। इसलिए आपको एक एक्सेप्शन मिलना चाहिए। लेकिन Rails का ऑटोलोड एक्सेप्शन नहीं फेंकता। इसके बजाय, यह A::MARCO लौटाता है।

# a.rb
module A
  MARCO = "polo"
end

# a/b.rb
module A::B
  def self.n
    puts MARCO # => "polo"
  end
end

# some_controller.rb
A::B.n()

निष्कर्ष?

यह सब सोचने के लिए बहुत कुछ है। मैं जहां संभव हो सोचने से बचना पसंद करता हूँ, इसलिए मैं मॉड्यूल A::B सिंटैक्स से दूर रहने की कोशिश करता हूँ। मैं उस मामले के बारे में नहीं सोच सकता जहां मैं जानबूझकर मॉड्यूल नेस्टिंग में हेरफेर करना चाहूंगा। यदि आप किसी के बारे में जानते हैं, तो मुझे उनके बारे में सुनना अच्छा लगेगा!

  1. रूबी केस स्टेटमेंट्स में महारत: बहुमुखी उपयोग और व्यावहारिक उदाहरण रूबी केस स्टेटमेंट्स में महारत: बहुमुखी उपयोग और व्यावहारिक उदाहरण

    जब भी आपको कुछ if / elsif स्टेटमेंट्स का उपयोग करने की आवश्यकता होती है तो आप इसके बजाय रूबी केस स्टेटमेंट का उपयोग करने पर विचार कर सकते हैं। इस पोस्ट में, आप कुछ अलग उपयोग के मामले सीखेंगे और यह वास्तव में हुड के नीचे कैसे काम करता है। नोट: अन्य प्रोग्रामिंग भाषाओं में इसे स्विच स्टेटमेंट के रूप

  1. सावधान: 12 Google खोजें जो आपको गुमराह कर सकती हैं सावधान: 12 Google खोजें जो आपको गुमराह कर सकती हैं

    निस्संदेह, Google हम सभी के लिए जानकारी प्राप्त करने का एकमात्र प्लेटफॉर्म बन चुका है। चाहे पास के बैंक शाखा का पता लगाना हो या बाजार की बड़ी कंपनियों के नवीनतम अपडेट जानने हों, हम Google की ओर ही रुख करते हैं। हमारे सवाल कितने भी छोटे या अजीब क्यों न हों, Google हमेशा हमें मनचाहे परिणाम या कम से कम

  1. विंडोज मेंटेनेंस की इन गलतियों से बचें बेहतर परफॉर्मेंस के लिए विंडोज मेंटेनेंस की इन गलतियों से बचें बेहतर परफॉर्मेंस के लिए

    तकनीक में प्रगति के साथ, उपयोगकर्ताओं ने अपने विंडोज कंप्यूटर को बनाए रखने और समय-समय पर इसे साफ करने के मूल तरीके को समझ लिया है ताकि यह स्वस्थ रहे। हालांकि, समय के साथ ऑपरेटिंग सिस्टम काफी बदल गया है, विशेष रूप से विंडोज 10, और इसके रखरखाव के तरीके भी बदल गए हैं। लेकिन उपयोगकर्ताओं को इसके बारे मे