2012-06-20 3 views
108

Voglio registrare l'attuale backtrace (stacktrace) in un'app Rails 3 senza un'eccezione. Qualche idea su come?Ottieni traccia dello stack corrente in Ruby senza generare un'eccezione

Perché lo voglio? Sto cercando di rintracciare le chiamate che vengono fatte quando Rails cerca un modello in modo che io possa scegliere una parte del processo da sovrascrivere (perché voglio cambiare il percorso della vista per un particolare controller sottoclasse).

Vorrei chiamarlo dal file: gems\actionpack-3.2.3\lib\action_dispatch\middleware\templates\rescues\missing_template.erb. So che non è una buona pratica, ma so che è a valle dello stack da cui proviene la ricerca di modelli.

+4

soluzione sporca: sollevare un'eccezione lì, salvare immediatamente il login e 'e.backtrace'. L'ho visto in uno dei progetti con cui lavoro. Non è l'approccio migliore, ma funziona. Spero di sentire una soluzione migliore da qualcun altro, però. –

+0

Brillante. Grazie. – JellicleCat

risposta

155

È possibile utilizzare 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 

uscita:

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

Molto utile, molto semplice - grazie! –

+0

Non è 'Kernel.caller' - con un punto? 'Kernel.new.caller' non è definito qui – ecoologic

+7

No, tecnicamente' caller' è un metodo di istanza. Dato che il modulo 'Kernel' è incluso in ogni classe Ruby (eccetto' BasicObject' in 1.9), è disponibile come metodo di istanza su qualsiasi oggetto (è privato, però). Non puoi chiamarlo come 'Kernel.new.caller' semplicemente perché non puoi istanziare un modulo (non ha il metodo' new'). –

3

Io lo uso per mostrare una pagina di errore personalizzata quando eccezioni sono sollevate.

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 
5

Provare a utilizzare

Thread.current.backtrace