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

रूबी में ऑब्जेक्ट मार्शलिंग में महारत: एक व्यावहारिक गाइड

इस लेख में, हम ऑब्जेक्ट मार्शलिंग में गोता लगाने जा रहे हैं। हम बताएंगे कि यह क्या है, Marshal मॉड्यूल को देखेंगे, और फिर एक उदाहरण के माध्यम से जाएंगे। हम फिर एक कदम और गहरे जाएंगे और _dump और self._load विधियों की तुलना करेंगे। चलते हैं!

ऑब्जेक्ट मार्शलिंग क्या है?

जब आप कोड लिख रहे होते हैं, तो आप किसी ऑब्जेक्ट को सहेजना और इसे किसी अन्य प्रोग्राम में ट्रांसमिट करना या अपने अगले प्रोग्राम निष्पादन में इसका पुन: उपयोग करना चाह सकते हैं। ऑब्जेक्ट मार्शलिंग का उपयोग साइडकिक में किया जाता है, उदाहरण के लिए; जब एक साइडकिक जॉब को रूबी ऑन रेल्स एप्लिकेशन में एन्क्यू किया जाता है, तो इस जॉब का एक सीरियलाइज़ेशन — जो एक ऑब्जेक्ट से ज्यादा कुछ नहीं है — रेडिस में डाला जाता है। साइडकिक प्रक्रिया तब इस JSON को डिसीरियलाइज़ करने और JSON से मूल जॉब को पुनर्गठित करने में सक्षम होती है।

कंप्यूटर प्रोग्रामिंग में, एक ऑब्जेक्ट के सीरियलाइज़ेशन और डिसीरियलाइज़ेशन की इस प्रक्रिया को हम आमतौर पर ऑब्जेक्ट मार्शलिंग कहते हैं। अब, आइए देखें कि रूबी ऑब्जेक्ट मार्शलिंग को संभालने के लिए मूल रूप से क्या प्रदान करती है।

Marshal मॉड्यूल

चूंकि रूबी एक पूर्ण ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग भाषा है, यह अपने स्टैंडर्ड लाइब्रेरी में Marshall मॉड्यूल का उपयोग करके ऑब्जेक्ट्स को सीरियलाइज़ और स्टोर करने का एक तरीका प्रदान करती है। यह आपको एक ऑब्जेक्ट को एक बाइट स्ट्रीम में सीरियलाइज़ करने की अनुमति देता है जिसे स्टोर किया जा सकता है और किसी अन्य रूबी प्रक्रिया में डिसीरियलाइज़ किया जा सकता है।

तो, आइए एक स्ट्रिंग को सीरियलाइज़ करें और सीरियलाइज़्ड ऑब्जेक्ट पर करीब से नज़र डालें।

hello_world = 'hello world!' serialized_string = Marshal.dump(hello_world) # => "\x04\bI\"\x11hello world!\x06:\x06ET" serialized_string.class # => String deserialized_hello_world = Marshal.load(serialized_string) # => "hello world!" hello_world.object_id # => 70204420126020 deserialized_hello_world.object_id # => 70204419825700

हम फिर अपने स्ट्रिंग को सीरियलाइज़ करने के लिए Marshal.dump मॉड्यूल विधि को कॉल करते हैं। हम रिटर्न वैल्यू को स्टोर करते हैं — जिसमें हमारा सीरियलाइज़्ड स्ट्रिंग होता है — serialized_string वेरिएबल में। इस स्ट्रिंग को एक फाइल में स्टोर किया जा सकता है और फाइल का पुन: उपयोग किसी अन्य प्रक्रिया में मूल ऑब्जेक्ट को पुनर्गठित करने के लिए किया जा सकता है। हम फिर मूल ऑब्जेक्ट को बाइट स्ट्रीम से पुनर्गठित करने के लिए Marshal.load विधि को कॉल करते हैं।

हम देख सकते हैं कि इस ताज़ा पुनर्गठित स्ट्रिंग का object_id hello_world स्ट्रिंग से अलग है, जिसका अर्थ है कि यह एक अलग ऑब्जेक्ट है, लेकिन इसमें वही डेटा है।

बहुत बढ़िया! लेकिन Marshal मॉड्यूल स्ट्रिंग को पुनर्निर्मित करने में कैसे सक्षम है? और, क्या होगा अगर मैं सीरियलाइज़ और डिसीरियलाइज़ करने के लिए किन एट्रिब्यूट्स पर नियंत्रण रखना चाहता हूँ?

ऑब्जेक्ट मार्शलिंग का एक ठोस उदाहरण

इन सवालों का जवाब देने के लिए, आइए User नामक एक कस्टम स्ट्रक्चर पर एक मार्शलिंग रणनीति लागू करें।

User = Struct.new(:fullname, :age, :roles) user = User.new('Mehdi Farsi', 42, [:admin, :operator])

User स्ट्रक्चर 3 एट्रिब्यूट्स को परिभाषित करता है: fullname, age, और roles। इस उदाहरण के लिए हमारे पास एक व्यावसायिक नियम है जहां हम केवल तभी सीरियलाइज़ करते हैं जब यह निम्नलिखित मानदंडों से मेल खाता है:

  • fullname में 64 से कम वर्ण हैं
  • roles सरणी में :admin भूमिका नहीं है

ऐसा करने के लिए, हम अपने कस्टम सीरियलाइज़ेशन रणनीति को लागू करने के लिए एक User#marshal_dump विधि को परिभाषित कर सकते हैं। यह विधि तब कॉल की जाएगी जब हम User स्ट्रक्चर के एक इंस्टेंस को पैरामीटर के रूप में Marshal.dump विधि को लागू करेंगे। आइए इस विधि को परिभाषित करें:

User = Struct.new(:age, :fullname, :roles) do def marshal_dump {}.tap do |result| result[:age] = age result[:fullname] = fullname if fullname.size <= 64 result[:roles] = roles unless roles.include? :admin end end end user = User.new(42, 'Mehdi Farsi', [:admin, :operator]) user_dump = Marshal.dump(user) # 'in User#marshal_dump' user_dump # => "\x04\bU:\tUser{\a:\bageI\"\x10Mehdi Farsi\x06:\x06ET:\rfullnamei/" 

उपरोक्त उदाहरण में, हम देख सकते हैं कि जब हम Marshal.dump(user) को लागू करते हैं तो हमारा User#marshal_dump विधि कॉल की जाती है। user_dump वेरिएबल में स्ट्रिंग होती है जो हमारे User इंस्टेंस का सीरियलाइज़ेशन है।

अब जब हमारे पास हमारा डंप है, तो आइए इसे डिसीरियलाइज़ करके अपने उपयोगकर्ता को पुनर्गठित करें। ऐसा करने के लिए, हम एक User#marshal_load विधि को परिभाषित करते हैं जो User डंप की डिसीरियलाइज़ेशन रणनीति को लागू करने के प्रभारी है।

तो आइए इस विधि को परिभाषित करें।

User = Struct.new(:age, :fullname, :roles) do def marshal_dump {}.tap do |result| result[:age] = age result[:fullname] = fullname if fullname.size <= 64 result[:roles] = roles unless roles.include? :admin end end def marshal_load(serialized_user) self.age = serialized_user[:age] self.fullname = serialized_user[:fullname] self.roles = serialized_user[:roles] || [] end end user = User.new(42, 'Mehdi Farsi', [:admin, :operator]) user_dump = Marshal.dump(user) # 'in User#marshal_dump' user_dump # => "\x04\bU:\tUser{\a:\bagei/:\rfullnameI\"\x10Mehdi Farsi\x06:\x06ET" original_user = Marshal.load(user_dump) # 'in User#marshal_load' original_user # => #<struct User age=42, fullname="Mehdi Farsi", roles=[]>

उपरोक्त उदाहरण में, हम देख सकते हैं कि जब हम Marshal.load(user_dump) को लागू करते हैं तो हमारा User#marshal_load method कॉल किया जाता है। original_user वेरिएबल में एक स्ट्रक्चर होता है जो हमारे उपयोगकर्ता इंस्टेंस का पुनर्गठन है।

ध्यान दें कि original_user.roles user.roles सरणी के समान नहीं है क्योंकि सीरियलाइज़ेशन के दौरान, user.roles में :admin भूमिका शामिल थी। इसलिए user.roles को user_dump वेरिएबल में सीरियलाइज़ नहीं किया गया था।

_dump और self._load विधियाँ

जब Marshal.dump और Marshal.load को लागू किया जाता है, तो ये विधियाँ पैरामीटर के रूप में पास किए गए ऑब्जेक्ट पर marshal_dump और marshal_load विधियों को कॉल करती हैं।

लेकिन, क्या होगा अगर मैं आपको बताऊं कि Marshal.dump और Marshal.load विधियाँ पैरामीटर के रूप में पास किए गए ऑब्जेक्ट पर _dump और self._load नामक दो अन्य विधियों को कॉल करने का प्रयास करती हैं?

_dump विधि

marshal_dump और _dump विधियों के बीच अंतर हैं:

  • _dump विधि का उपयोग करते समय आपको सीरियलाइज़ेशन रणनीति को निचले स्तर पर संभालने की आवश्यकता होती है — आपको उस डेटा को दर्शाने वाली एक स्ट्रिंग लौटाने की आवश्यकता होती है जिसे सीरियलाइज़ करना है
  • यदि दोनों परिभाषित हैं तो marshal_dump विधि _dump पर प्राथमिकता लेती है

आइए निम्नलिखित उदाहरण पर एक नज़र डालें:

User = Struct.new(:age, :fullname, :roles) do def _dump level [age, fullname].join(':') end end user = User.new(42, 'Mehdi Farsi', [:admin, :operator]) Marshal.dump(user) # => "\x04\bIu:\tUser\x1342:Mehdi Farsi\x06:\x06EF"

User#_dump विधि में, हमें सीरियलाइज़ेशन ऑब्जेक्ट को इंस्टेंटिएट और लौटाना होगा — वह स्ट्रिंग जो आपके सीरियलाइज़ेशन को दर्शाती है।

निम्नलिखित उदाहरण में, हम User#marshal_dump और User#_dump विधियों को परिभाषित करते हैं और यह देखने के लिए एक स्ट्रिंग लौटाते हैं कि कौन सी विधि कॉल की जाती है

User = Struct.new(:age, :fullname, :roles) do def marshal_dump 'in User#marshal_dump' end def _dump level 'in User#_dump' end end user = User.new(42, 'Mehdi Farsi', [:admin, :operator]) user_dump = Marshal.dump(user) # "in User#marshal_dump"

हम देख सकते हैं कि केवल User#marshal_dump को कॉल किया जाता है भले ही दोनों परिभाषित हों।

self._load विधि

अब, आइए marshal_load और _load विधियों को देखें।

marshal_load और _load विधियों के बीच अंतर हैं:

  • _load विधि का उपयोग करते समय आपको डिसीरियलाइज़ेशन रणनीति को निचले स्तर पर संभालने की आवश्यकता होती है — आप मूल ऑब्जेक्ट को इंस्टेंटिएट करने के प्रभारी हैं
  • marshal_load विधि एक आर्गुमेंट के रूप में एक डिसीरियलाइज़्ड ऑब्जेक्ट लेती है जब self._load विधि सीरियलाइज़्ड स्ट्रिंग को आर्गुमेंट के रूप में लेती है
  • marshal_load विधि एक इंस्टेंस विधि है जब self._load एक क्लास विधि है

आइए निम्नलिखित उदाहरण पर एक नज़र डालें:

User = Struct.new(:age, :fullname, :roles) do def _dump level [age, fullname].join(':') end def self._load serialized_user user_info = serialized_user.split(':') new(*user_info, Array.new) end end user = User.new(42, 'Mehdi Farsi', [:admin, :operator]) user_dump = Marshal.dump(user) user_dump # => "\x04\bIu:\tUser\x1342:Mehdi Farsi\x06:\x06EF" original_user = Marshal.load(user_dump) original_user # => #<struct User age="Mehdi Farsi", fullname=42, roles=[]>

User._load विधि में:

  • User#_dump विधि द्वारा लौटाई गई स्ट्रिंग को डिसीरियलाइज़ करते हैं
  • डिसीरियलाइज़्ड जानकारी पास करके एक नया User इंस्टेंटिएट करते हैं

हम देख सकते हैं कि हम अपने मूल उपयोगकर्ता को पुनर्गठित करने के लिए उपयोग किए जाने वाले ऑब्जेक्ट को आवंटित और इंस्टेंटिएट करने के प्रभारी हैं।

तो Marshal.load युग्मित marshal_load के साथ पुनर्गठित मूल ऑब्जेक्ट को इंस्टेंटिएट करने का ख्याल रखता है। फिर यह ताज़ा इंस्टेंटिएटेड ऑब्जेक्ट पर सीरियलाइज़्ड ऑब्जेक्ट को आर्गुमेंट के रूप में पास करके marshal_load विधि को कॉल करता है।

इसके विपरीत, _load से युग्मित Marshal.load की कॉल self._load क्लास विधि को इसके प्रभारी होने देती है:

  • _dump विधि द्वारा लौटाए गए डेटा को डिसीरियलाइज़ करना
  • पुनर्गठित मूल ऑब्जेक्ट को इंस्टेंटिएट करना

निष्कर्ष

आपकी आवश्यकताओं के आधार पर, आप एक उच्च या निम्न सीरियलाइज़ेशन/डिसीरियलाइज़ेशन रणनीति लागू करने का निर्णय ले सकते हैं। ऐसा करने के लिए, आप उपयुक्त Marshal हुक विधियों के साथ Marshal मॉड्यूल का उपयोग कर सकते हैं।

Voilà!

  1. Ruby में Lambdas में महारत हासिल करें: बुनियादी से उन्नत तकनीकें तक Ruby में Lambdas में महारत हासिल करें: बुनियादी से उन्नत तकनीकें तक

    ब्लॉक Ruby का इतना महत्वपूर्ण हिस्सा हैं, उनके बिना भाषा की कल्पना करना कठिन है। लेकिन लैम्ब्डा? कौन लैम्ब्डा से प्यार करता है? आप वर्षों तक बिना एक का उपयोग किए जा सकते हैं। वे लगभग एक बीते युग के अवशेष लगते हैं। ...लेकिन यह पूरी तरह सच नहीं है। लैम्ब्डा की आस्तीन में कुछ दिलचस्प तरकीबें हैं एक बार

  1. Ruby 2.6 में 9 प्रमुख संवर्द्धन का अन्वेषण Ruby 2.6 में 9 प्रमुख संवर्द्धन का अन्वेषण

    Ruby का एक नया संस्करण नई सुविधाओं और प्रदर्शन सुधारों के साथ आ रहा है। क्या आप परिवर्तनों के साथ बने रहना चाहेंगे? आइए एक नज़र डालते हैं! अंतहीन रेंज (Endless Ranges) Ruby 2.5 और पुराने संस्करण पहले से ही अंतहीन रेंज का एक रूप (Float::INFINITY के साथ) का समर्थन करते हैं, लेकिन Ruby 2.6 इसे अगले स्त

  1. रूबी के फ्रीज मेथड को समझना: ऑब्जेक्ट म्यूटेबिलिटी समझाया गया रूबी के फ्रीज मेथड को समझना: ऑब्जेक्ट म्यूटेबिलिटी समझाया गया

    किसी ऑब्जेक्ट के म्यूटेबल होने का क्या अर्थ है? फैंसी शब्दों को आपको भ्रमित न करने दें, म्यूटेबिलिटी का सीधा सा अर्थ है कि किसी ऑब्जेक्ट की आंतरिक स्थिति को बदला जा सकता है। यह उन ऑब्जेक्ट्स को छोड़कर सभी ऑब्जेक्ट्स का डिफ़ॉल्ट है जिन्हें फ्रीज किया गया है, या जो विशेष ऑब्जेक्ट्स की सूची का हिस्सा ह