रूबी में बचाव और अपवाद और दूसरे प्रकार के अपवाद को फिर से उठाना एक आम पैटर्न है। एक्शन व्यू इसका वास्तव में एक स्पष्ट उदाहरण है। जैसा कि मैंने TracePoint के बारे में पहले के ब्लॉग पोस्ट में उल्लेख किया था, ActionView आपके टेम्प्लेट में जो भी अपवाद होता है उसे निगल लेता है और उन्हें ActionView::TemplateError
के रूप में फिर से उठाता है। ।
कभी-कभी यह काफी नहीं होता है। आपको वास्तव में उस मूल अपवाद की आवश्यकता है क्योंकि इसमें कुछ डेटा है जो आपको किसी समस्या को हल करने में मदद करेगा। सौभाग्य से, रूबी 2.1 के रूप में, आप ऐसा करने के लिए अपवाद # कारण विधि का उपयोग कर सकते हैं।
आइए देखें कि यह व्यवहार में कैसे काम करता है। यहां, हम एक NoMethodError
बढ़ाते हैं , फिर इसे तुरंत निगल लें और RuntimeError
बढ़ाएं . फिर हम RuntimeError
. को पकड़ लेते हैं और मूल NoMethodError
. प्राप्त करने के लिए #cause का उपयोग करें ।
def fail_and_reraise
raise NoMethodError
rescue
raise RuntimeError
end
begin
fail_and_reraise
rescue => e
puts "#{ e } caused by #{ e.cause }"
end
नेस्टेड बैकट्रेस और कस्टम एट्रिब्यूट
#cause विधि वास्तव में मूल अपवाद वस्तु लौटाती है। इसका मतलब है कि आप किसी भी मेटाडेटा तक पहुंच सकते हैं जो मूल अपवाद का हिस्सा था। आप मूल बैकट्रेस भी प्राप्त कर सकते हैं।
class EatingError < StandardError
attr_reader :food
def initialize(food)
@food = food
end
end
def fail_and_reraise
raise EatingError.new("soup")
rescue
raise RuntimeError
end
begin
fail_and_reraise
rescue => e
puts "#{ e } caused by #{ e.cause } while eating #{ e.cause.food }"
puts e.cause.backtrace.first
end
अनंत और उससे आगे तक!
हालांकि उपरोक्त उदाहरण केवल एक स्तर गहरे हैं, रूबी में नेस्टेड अपवादों में कई स्तर हो सकते हैं। मुझे आश्चर्य होगा अगर आपको कभी भी चार में से तीन स्तरों से अधिक गहराई तक जाने की आवश्यकता हो।
... लेकिन सिर्फ मनोरंजन के लिए मैंने सोचा कि मैं 100-स्तर के गहरे नेस्टेड अपवाद बनाने की कोशिश करूंगा। यह कोड का एक मूर्खतापूर्ण छोटा टुकड़ा है, और मुझे आशा है कि आप इसे उत्पादन में कभी नहीं देखेंगे।
def recursively_raise(c=0)
raise "Level #{ c }"
rescue => e
if c < 100
recursively_raise(c + 1)
else
recursively_print(e)
end
end
def recursively_print(e)
if e
puts e
recursively_print(e.cause)
end
end
recursively_raise()
# ... Prints the following:
# Level 100
# Level 99
# Level 98
# etc.