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

रूबी रेस्क्यू को उन्नत करें: डायनामिक एक्सेप्शन मिलान

जब आप रूबी में एक रेस्क्यू क्लॉज का उपयोग करते हैं, तो आप निर्दिष्ट कर सकते हैं कि आप किस प्रकार के एक्सेप्शन को रेस्क्यू करना चाहते हैं। आपको बस एक्सेप्शन क्लास की एक सूची प्रदान करने की आवश्यकता है जैसे:

begin raise RuntimeError rescue RuntimeError, NoMethodError puts "rescued!" end 

लेकिन क्या होगा यदि आप कोड लिखते समय नहीं जानते कि एक्सेप्शन क्लास क्या होगी? सबसे स्पष्ट उत्तर है सभी एक्सेप्शन को रेस्क्यू करना, किसी प्रकार का परीक्षण करना और फिर उन एक्सेप्शन को फिर से उठाना जो पास नहीं होते। कुछ इस तरह:

begin raise "FUBAR! The ship's going down!" rescue => e raise unless e.message =~ /^FUBAR/ ... do something ... end 

लेकिन यह बहुत उबाऊ है! साथ ही, यह बहुत DRY दृष्टिकोण नहीं है। यह बहुत अधिक दिलचस्प होगा अगर हम किसी तरह रेस्क्यू क्लॉज को बता सकें कि केवल हमारी शर्तों से मेल खाने वाले एक्सेप्शन को रेस्क्यू करें। और चूंकि यह रूबी है, हम ऐसा कर सकते हैं!

रेस्क्यू एक्सेप्शन से कैसे मिलान करता है

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

मिलान कुछ इस तरह दिखता है:

exception_classes_to_rescue.any? do |c| c === raised_exception.class end 

रूबी में हर दूसरे ऑपरेटर की तरह, === केवल एक मेथड है। इस मामले में यह c का एक मेथड है। तो अगर हम अपना खुद का === मेथड परिभाषित करते तो हम क्या कर सकते थे?

नीचे दिए गए उदाहरण में मैं Anything नामक एक क्लास बना रहा हूँ जहां Anything === x x के किसी भी मान के लिए सही लौटाता है। यदि मैं इस क्लास को रेस्क्यू के लिए एक तर्क के रूप में देता हूँ, तो यह सभी एक्सेप्शन को रेस्क्यू कर लेता है।

class Anything def self.===(exception) true end end begin raise EOFError rescue Anything puts "It rescues ANYTHING!" end 

हालांकि सभी एक्सेप्शन को रेस्क्यू करने के बहुत बेहतर तरीके हैं, यह कोड दिलचस्प है क्योंकि यह हमें दो चीजें दिखाता है:

  1. आप रेस्क्यू क्लॉज को उन क्लास दे सकते हैं जो Exception से इनहेरिट नहीं करते, जब तक वे === को लागू करते हैं

  2. यदि आप === को नियंत्रित करते हैं, तो आप नियंत्रित कर सकते हैं कि कौन से एक्सेप्शन रेस्क्यू होते हैं।

मैसेज के आधार पर एक्सेप्शन रेस्क्यू करना

अब जो हम जानते हैं, उसके आधार पर, ऐसा कोड लिखना सरल है जो केवल तभी एक्सेप्शन को रेस्क्यू करता है जब एक्सेप्शन का मैसेज किसी पैटर्न से मेल खाता हो।

class AllFoobarErrors def self.===(exception) # rescue all exceptions with messages starting with FOOBAR exception.message =~ /^FOOBAR/ end end begin raise EOFError, "FOOBAR: there was an eof!" rescue AllFoobarErrors puts "rescued!" end 

कस्टम एट्रिब्यूट के आधार पर एक्सेप्शन रेस्क्यू करना

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

एक पल के लिए कल्पना करें कि आपके पास एक एक्सेप्शन है जिसमें "severity" नामक एक कस्टम एट्रिब्यूट है। आप एक्सेप्शन की सभी "कम गंभीरता" वाली घटनाओं को निगलना चाहेंगे, लेकिन किसी भी "उच्च गंभीरता" वाली घटनाओं को पास होने देंगे। आप इसे इस तरह लागू कर सकते हैं:

class Infraction < StandardError attr_reader :severity def initialize(severity) @severity = severity end end class LowSeverityInfractions def self.===(exception) exception.is_a?(Infraction) && exception.severity == :low end end begin raise Infraction.new(:low) rescue LowSeverityInfractions puts "rescued!" end 

इसे डायनामिक बनाना

यह सब बहुत अच्छा है, लेकिन इसमें बहुत सारा बॉयलरप्लेट कोड शामिल है। प्रत्येक मैचर के लिए मैन्युअल रूप से अलग-अलग क्लास को परिभाषित करना अत्यधिक लगता है। सौभाग्य से हम थोड़े मेटाप्रोग्रामिंग का उपयोग करके इसे काफी हद तक DRY कर सकते हैं।

नीचे दिए गए उदाहरण में, हम एक मेथड को परिभाषित कर रहे हैं जो हमारे लिए मैचर क्लास उत्पन्न करता है। आप एक ब्लॉक के माध्यम से मिलान तर्क प्रदान करते हैं, और मैचर जनरेटर एक नई क्लास बनाता है जो ब्लॉक को अपने === मेथड के अंदर उपयोग करता है।

def exceptions_matching(&block) Class.new do def self.===(other) @block.call(other) end end.tap do |c| c.instance_variable_set(:@block, block) end end begin raise "FOOBAR: We're all doomed!" rescue exceptions_matching { |e| e.message =~ /^FOOBAR/ } puts "rescued!" end 

एक दाना नमक का

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


  1. Hotwire के साथ Rails ऐप्स को तेज़ करें: JavaScript के बिना सर्वर-साइड रेंडरिंग Hotwire के साथ Rails ऐप्स को तेज़ करें: JavaScript के बिना सर्वर-साइड रेंडरिंग

    यदि आप पेज परिवर्तनों और फॉर्म सबमिशन को तेज़ करने और जटिल पेज को बिना कोई JavaScript कोड लिखे घटकों में विभाजित करने का तरीका ढूंढ रहे हैं, तो यह पोस्ट आपको Hotwire के साथ Rails को अगले स्तर पर ले जाने में मदद करेगी। यह लेख आपको सर्वर-साइड रेंडरिंग के लिए एक टूल का उपयोग करना सिखाएगा। Hotwire क्या

  1. Pry में अपवाद हैंडलिंग में महारत हासिल करें: Rails कंसोल के लिए उन्नत तकनीकें Pry में अपवाद हैंडलिंग में महारत हासिल करें: Rails कंसोल के लिए उन्नत तकनीकें

    यदि आप मेरी तरह हैं, तो आप Rails कंसोल का बहुत उपयोग करते हैं। और अब तक मुझे लगता है कि हर कोई सहमत है कि Pry, Rails कंसोल के लिए अब तक की सबसे अच्छी चीज है... ठीक है, कभी भी। Pry में अंतर्निहित कुछ वास्तव में कूल फीचर्स हैं जो अपवादों के साथ काम करना सादे पुराने IRB की तुलना में बहुत आसान बनाते हैं

  1. विंडोज 10 पीसी को डायनामिक लॉक से सुरक्षित करें: चरण-दर-चरण गाइड विंडोज 10 पीसी को डायनामिक लॉक से सुरक्षित करें: चरण-दर-चरण गाइड

    विंडोज 10 द्वारा जोड़ी गई नई सुविधाओं में से एक है, डायनामिक लॉक। यह विंडोज 10 में प्रदान की गई एक और छिपी हुई सुविधा है और इसे क्रिएटर्स अपडेट के साथ लॉन्च किया गया था। हालांकि, कई यूज़र्स अभी भी इस सुविधा से अनजान हैं। तो, इस लेख में, हम जानेंगे कि डायनामिक लॉक क्या है और हम इसका उपयोग कैसे कर सक