रेल के साथ काम करने के बारे में एक अच्छी बात यह है कि जब विकास में कुछ गलत होता है, तो आपको वास्तव में एक अच्छा त्रुटि विवरण पृष्ठ मिलता है। आपको एक अच्छा बैकट्रेस मिलता है, जिसमें आपके ऐप से संबंधित भागों को हाइलाइट किया जाता है। आप पोस्ट किए गए पैरा को देख सकते हैं, साथ ही पर्यावरण और सत्र चर का निरीक्षण कर सकते हैं।
आज हम इस पर एक नज़र डालने जा रहे हैं कि ये फैंसी त्रुटि पृष्ठ कैसे काम करते हैं।
खुले एक्शनपैक को क्रैक करना
आज हम जिस फ़ाइल के बारे में बात करने जा रहे हैं, वह है Actionpack/lib/action_dispatch/middleware/debug_exceptions.rb. जब उन विकास मोड त्रुटि पृष्ठों को प्रदर्शित करने की बात आती है तो यह अधिकांश भारी भारोत्तोलन करता है। यदि आप इस बारे में उत्सुक हैं कि उत्पादन मोड त्रुटि स्क्रीन कहाँ से आती है, तो public_exceptions.rb देखें।
रैक मिडलवेयर
यदि आप रैक मिडलवेयर से परिचित नहीं हैं, तो अवधारणा सरल है। यह आपको HTTP अनुरोधों को आपके ऐप पर पहुंचने से पहले इंटरसेप्ट करने और ऐप के आउटपुट को उपयोगकर्ता के पास वापस जाने से पहले इंटरसेप्ट करने की अनुमति देता है।
यहाँ एक साधारण मिडलवेयर है जो कुछ भी दिलचस्प नहीं करता है।
class MyMiddleware
def initialize(app)
@app = app
end
def call(env)
@app.call(env)
end
end
रैक मिडलवेयर के माध्यम से सभी अपवादों को रेस्क्यू करना
आपके ऐप में होने वाला कोई भी अपवाद @app.call() पर कॉल करने के परिणामस्वरूप होता है। इसलिए रैक ऐप में सभी अपवादों को बचाना उतना ही आसान है जितना कि मिडलवेयर में रेस्क्यू क्लॉज जोड़ना।
def call(env)
@app.call(env)
rescue StandardError => exception
# this is a method we have to provide to generate the exception page
render_exception(env, exception)
end
कॉल विधि से लौटाई गई किसी भी चीज़ को एक सामान्य वेब पेज के रूप में माना जाएगा। तो रेंडर_एक्सप्शन द्वारा लौटाई गई सामग्री मूल प्रतिक्रिया को बदल देती है।
अपवाद को रेंडर करना
मैंने ActionDispatch::DebugExceptions से रेंडर_एक्सप्शन विधि का अंश लिया है। जैसा कि आप देख सकते हैं, यह केवल प्रासंगिक डेटा को अपवाद से खींचता है और इसे एक ईआरबी टेम्पलेट में फीड करता है।
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
अन्य उपयोग
अपवादों के साथ बहुत सारी रोचक चीजें करने के लिए आप इस रैक मिडलवेयर चाल का उपयोग कर सकते हैं। यहां हनीबैगर में, हम इसका उपयोग त्रुटियों को रोकने और उन्हें हमारे एपीआई में रिकॉर्ड करने के लिए करते हैं। यह कोड हम इसे करने के लिए उपयोग करते हैं:
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