रूबी में एक अपवाद को पकड़ने के बाद रेरीज़ (एक ही अपवाद)


84

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

class Logo
  def process
    begin
      @processed_logo = LogoProcessor::create_image(self.src)
    rescue CustomException
      raise CustomException
    end
  end
end

module LogoProcessor
  def self.create_image
    raise CustomException if some_condition
  end
end

जवाबों:


168

कभी कभी हम सिर्फ जानना चाहता हूँ एक त्रुटि हुआ , वास्तव में बिना संभाल त्रुटि।

अक्सर ऐसा होता है कि त्रुटियों को संभालने के लिए जिम्मेदार व्यक्ति ऑब्जेक्ट का उपयोगकर्ता होता है: कॉल करने वाला। क्या होगा यदि हम त्रुटि में रुचि रखते हैं, लेकिन उस जिम्मेदारी को स्वीकार नहीं करना चाहते हैं? हम त्रुटि को सुधारते हैं, हमें जो कुछ भी करना है उसे करें और फिर सिग्नल को स्टैक तक प्रचारित करें जैसे कि कुछ भी नहीं हुआ था।

उदाहरण के लिए, क्या होगा यदि हम त्रुटि संदेश को लॉग इन करना चाहते हैं और फिर कॉलर को इससे निपटने दें?

begin
  this_will_fail!
rescue Failure => error
  log.error error.message
  raise
end

raiseबिना किसी तर्क के कॉल करना अंतिम त्रुटि को बढ़ाएगा। हमारे मामले में, हम फिर से उठा रहे हैं error

आपके प्रश्न में प्रस्तुत उदाहरण में, त्रुटि को फिर से उठाना केवल आवश्यक नहीं है। आप बस इसे स्वाभाविक रूप से स्टैक को फैलाने दे सकते हैं। आपके उदाहरण में एकमात्र अंतर यह है कि आप एक नई त्रुटि ऑब्जेक्ट बना रहे हैं और इसे पिछले एक को फिर से बढ़ाने के बजाय बढ़ा रहे हैं।


दिलचस्प। मेरा सवाल यह है कि अगर मैं प्रक्रिया की परिभाषा में त्रुटि को नहीं पकड़ता हूं, तो मुझे प्रक्रिया विधि को कॉल करने पर इसे पकड़ने की आवश्यकता होगी, उदाहरण के लिए:, begin @logo.process; rescue...लेकिन फिर मैं प्रक्रिया द्वारा शुरू किए गए अपवाद को नहीं पकड़ पाऊंगा, लेकिन इस प्रक्रिया के भीतर से कुछ कहा जाता है। क्या ऐसा करना सही है?
होममर स्मिथ २०'१४

2
यह stacktraceमूल अपवाद से ढीला होगा , आप संभवतः अपवाद को शामिल करना चाहते हैं causeजो रूबी में उपलब्ध है 2.1
bjhaid

4
raiseइस जवाब के तरीके में @bjhaid कॉलिंग पूरी तरह से मूल अपवाद को संरक्षित करती है, जिसमें शामिल है backtracecauseइस मामले पर लागू नहीं होता है। बल्कि, यह स्वचालित रूप से आबाद हो जाता है जब एक rescueब्लॉक एक नया अपवाद उठाता है।
प्रतिनिधि

@HommerSmith: क्या होगा अगर लाइन से पहले (इस मामले में log.error, लेकिन यह कुछ भी हो सकता है) विफल रहता है? मैं इसे "सुनिश्चित" करने के बारे में सोच रहा हूं, लेकिन, यह सुनिश्चित करने के अंदर कि मुझे "उठाना" के तर्क के रूप में त्रुटि के संदर्भ का उपयोग करना होगा। तुम उसके बारे में क्या सोचते हो?
jgomo3

1
@ RafałCieślak हर बार जब कोई त्रुटि उठती है, तो उसे $!वैश्विक चर को सौंपा जाता है । raiseतर्कों के बिना कॉल करना $!, निहित त्रुटि को उठाता है , प्रभावी रूप से अंतिम त्रुटि को बढ़ाता है। हालांकि, स्थानीय चर raise errorमें निहित त्रुटि को बढ़ाएगा error, जिसमें निहित एक ही वस्तु हो सकती है या नहीं भी हो सकती है $!। मेरे उदाहरण में, $!जैसा है वैसा ही है error। हालाँकि, ऐसा करना भी संभव है:error = Exception.new; raise error
मथियस मोरेरा

3

यह मूल के समान त्रुटि को बढ़ाएगा, लेकिन आप संदेश को अनुकूलित कर सकते हैं।

rescue StandardError => e
  raise e.class, "Message: #{e.message}"

मैं StandardError को पकड़ने के लिए इसके बुरे विचार का सुझाव दूंगा क्योंकि इसमें सभी प्रकार के निचले स्तर के कार्य शामिल हैं और यह आपके प्रोग्राम को लटका सकता है।
पॉल व्हाइटहेड

1
मेरा मानना ​​है कि यह नियम के लिए एक "अपवाद" है, क्योंकि हम तुरंत अपवाद को फिर से बढ़ा रहे हैं।
फ्रीपेंडर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.