रूबी में मौजूदा स्टैक ट्रेस एक अपवाद को उठाए बिना प्राप्त करें


139

मैं एक अपवाद होने के बिना रेल 3 एप्लिकेशन में वर्तमान बैकट्रेस (स्टैकट्रेस) को लॉग इन करना चाहता हूं । कोई विचार कैसे?

मुझे यह क्यों चाहिए? मैं उस कॉल को ट्रेस करने की कोशिश कर रहा हूं जब रेल एक टेम्पलेट की तलाश में है ताकि मैं ओवरराइड करने के लिए प्रक्रिया का एक हिस्सा चुन सकूं (क्योंकि मैं एक विशेष उप-नियंत्रक नियंत्रक के लिए दृश्य पथ को बदलना चाहता हूं)।

मैं इसे फ़ाइल से कॉल करना चाहूंगा gems\actionpack-3.2.3\lib\action_dispatch\middleware\templates\rescues\missing_template.erb:। मुझे पता है कि यह सबसे अच्छा अभ्यास नहीं है, लेकिन मुझे पता है कि यह स्टैक के नीचे की तरफ है जहां से टेम्प्लेट की खोज होती है।


4
गंदा समाधान: वहां एक अपवाद बढ़ाएं, इसे तुरंत बचाएं और लॉग करें e.backtrace। मैंने इसे उन परियोजनाओं में से एक में देखा है, जिनके साथ मैं काम कर रहा हूं। सबसे अच्छा दृष्टिकोण नहीं है, लेकिन यह काम करता है। हालांकि किसी और से बेहतर समाधान सुनने की उम्मीद है।
KL-7

जवाबों:


185

आप उपयोग कर सकते हैं Kernel#caller:

# /tmp/caller.rb

def foo 
  puts caller # Kernel#caller returns an array of strings
end

def bar 
  foo 
end

def baz 
  bar 
end

baz

आउटपुट:

caller.rb:8:in `bar'
caller.rb:12:in `baz'
caller.rb:15:in `<main>'

यह नहीं है Kernel.caller- एक डॉट के साथ? Kernel.new.callerयहाँ पर परिभाषित नहीं किया गया है
ईकोलॉजिकल

8
नहीं, तकनीकी रूप callerसे एक उदाहरण विधि है। चूंकि Kernelमॉड्यूल हर रूबी वर्ग ( BasicObject1.9 को छोड़कर ) में शामिल है, यह किसी भी वस्तु पर उदाहरण विधि के रूप में उपलब्ध है (यह निजी है, हालांकि)। आप इसे Kernel.new.callerकेवल इसलिए नहीं कह सकते क्योंकि आप किसी मॉड्यूल को इंस्टेंट नहीं कर सकते (यह newविधि नहीं है )।
KL-7

यह किसी भी कॉल करने वाले को छोड़ने के लिए एक पैरामीटर का समर्थन करता है; देखें: stackoverflow.com/a/3829269/520567
akostadinov

7
सुंदर प्रिंट उपयोग के लिए - Rails.logger.debug caller.join("\n")या puts caller.join("\n")। धन्यवाद।
जिग्नेश गोहेल

20

प्रयोग करके देखें

Thread.current.backtrace

1
इस उत्तर का लाभ यह है कि इसमें बैकट्रेस में वर्तमान विधि शामिल है , जबकि Kernel#callerवर्तमान पद्धति को छोड़ देता है। उदाहरण के MyClass.new.returns_caller => ["(irb):42:in 'irb_binding'",...] लिए जैसे ही मददगार नहीं है MyClass.new.returns_thread_backtrace => ["(irb):38:in 'backtrace'","(irb):38:in 'returns_thread_backtrace'","(irb):43:in 'irb_binding'",...]
stwr667

6

जब अपवाद उठाया जाता है तो मैं एक कस्टम त्रुटि पृष्ठ दिखाने के लिए इसका उपयोग करता हूं।

rescue_from Exception do |exception|
  logger.error exception.class
  logger.error exception.message
  logger.error exception.backtrace.join "\n"
  @exception = exception


  # ExceptionNotifier::Notifier.exception_notification env, @exception

  respond_to do |format|
    if [AbstractController::ActionNotFound, ActiveRecord::RecordNotFound, ActionController::RoutingError, ActionController::UnknownAction].include?(exception.class)
      format.html { render :template => "errors/404", :status => 404 }
      format.js   { render :nothing => true, :status => 404 }
      format.xml  { render :nothing => true, :status => 404 }
    elsif exception.class == CanCan::AccessDenied
      format.html {
        render :template => "errors/401", :status => 401 #, :layout => 'application'
      }
      # format.js   { render :json => { :errors => [exception.message] }, :status => 401 }
      # format.js   { render :js => 'alert("Hello 401")' }
      format.js   { render :template => 'errors/401.js.erb' }

    else
      ExceptionNotifier::Notifier.exception_notification(env, exception).deliver        
      format.html { render :template => "errors/500", :status => 500 } #, :layout => 'im2/application' }
      # format.js   { render :nothing => true, :status => 500 }
      format.js   { render :template => 'errors/500.js.erb' }

    end
  end
end
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.