Rails के साथ काम करने की अच्छी चीजों में से एक यह है कि जब विकास में कुछ गलत होता है, तो आपको वास्तव में एक अच्छा त्रुटि विवरण पेज मिलता है। आपको एक अच्छा बैकट्रेस मिलता है, जिसमें आपके ऐप के लिए प्रासंगिक भाग हाइलाइट किए गए होते हैं। आप देख सकते हैं कि कौन से पैरामीटर पोस्ट किए गए थे, साथ ही पर्यावरण और सत्र चर का निरीक्षण कर सकते हैं।
आज हम यह देखने जा रहे हैं कि ये फैंसी त्रुटि पेज कैसे काम करते हैं।

Actionpack खोलना
आज हम जिस फ़ाइल से ज्यादातर चिंतित होंगे वह है actionpack/lib/action_dispatch/middleware/debug_exceptions.rb। यह उन विकास मोड त्रुटि पेज को प्रदर्शित करने के मामले में अधिकांश भारी काम करता है। यदि आप इस बारे में उत्सुक हैं कि प्रोडक्शन मोड त्रुटि स्क्रीन कहां से आती हैं, तो public_exceptions.rb देखें।
Rack मिडलवेयर
यदि आप Rack मिडलवेयर से परिचित नहीं हैं, तो अवधारणा सरल है। यह आपको HTTP अनुरोधों को आपके ऐप तक पहुंचने से पहले इंटरसेप्ट करने की अनुमति देता है, और ऐप के आउटपुट को उपयोगकर्ता के पास वापस जाने से पहले इंटरसेप्ट करने की अनुमति देता है।
यहाँ एक सरल मिडलवेयर है जो कुछ दिलचस्प नहीं करता।
class MyMiddleware def initialize(app) @app = app end def call(env) @app.call(env) end end
Rack मिडलवेयर के माध्यम से सभी अपवादों को रेस्क्यू करना
आपके ऐप में होने वाला कोई भी अपवाद @app.call() को कॉल करने के परिणामस्वरूप होता है। इसलिए Rack ऐप में सभी अपवादों को रेस्क्यू करना मिडलवेयर में एक रेस्क्यू क्लॉज जोड़ने जितना सरल है।
def call(env) @app.call(env) rescue StandardError => exception # यह एक मेथड है जिसे हमें अपवाद पेज उत्पन्न करने के लिए प्रदान करना होगा render_exception(env, exception) end
कॉल मेथड से वापस की गई किसी भी चीज़ को सामान्य वेब पेज के रूप में माना जाएगा। इसलिए render_exception द्वारा वापस की गई सामग्री मूल प्रतिक्रिया को प्रतिस्थापित करती है।
अपवाद रेंडर करना
मैंने ActionDispatch::DebugExceptions से render_exception मेथड को उद्धृत किया है। जैसा कि आप देख सकते हैं, यह केवल अपवाद से प्रासंगिक डेटा निकालता है और इसे ERB टेम्पलेट में फीड करता है।
def render_exception(env, exception) wrapper = ExceptionWrapper.new(env, exception) log_error(env, wrapper) if env['action_dispatch.show_detailed_exceptions'] request = Request.new(env) template = ActionView::Base.new([RESCUES_TEMPLATE_PATH], request: request, exception: wrapper.exception, application_trace: wrapper.application_trace, framework_trace: wrapper.framework_trace, full_trace: wrapper.full_trace, routes_inspector: routes_inspector(exception), source_extract: wrapper.source_extract, line_number: wrapper.line_number, file: wrapper.file ) file = "rescues/#{wrapper.rescue_template}" if request.xhr? body = template.render(template: file, layout: false, formats: [:text]) format = "text/plain" else body = template.render(template: file, layout: 'rescues/layout') format = "text/html" end render(wrapper.status_code, body, format) else raise exception end end def render(status, body, format) [status, {'Content-Type' => "#{format}; charset=#{Response.default_charset}", 'Content-Length' => body.bytesize.to_s}, [body]] end
अन्य उपयोग
आप इस Rack मिडलवेयर ट्रिक का उपयोग अपवादों के साथ बहुत सी दिलचस्प चीजें करने के लिए कर सकते हैं। यहां Honeybadger पर, हम इसका उपयोग त्रुटियों को इंटरसेप्ट करने और उन्हें हमारे API पर रिकॉर्ड करने के लिए करते हैं। यहाँ वह कोड है जिसका हम उपयोग करते हैं:
def call(env) config.with_request(::Rack::Request.new(env)) do begin env['honeybadger.config'] = config response = @app.call(env) rescue Exception => raised env['honeybadger.error_id'] = notify_honeybadger(raised, env) raise end framework_exception = framework_exception(env) if framework_exception env['honeybadger.error_id'] = notify_honeybadger(framework_exception, env) end response end ensure Honeybadger.context.clear! end