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

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

बचाव अपवादों से कैसे मेल खाता है

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

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

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

कस्टम विशेषताओं के आधार पर अपवादों को बचाना

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

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

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

इसे गतिशील बनाना

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

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

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. रेल के साथ हॉटवायर का उपयोग करना

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

  1. Pry . में अपवादों के साथ कार्य करना

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

  1. डायनेमिक लॉक फीचर के साथ विंडोज 10 को कैसे सुरक्षित करें

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