在Ruby中获取当前堆栈跟踪而不会引发异常

Jel*_*Cat 127 ruby stack-trace

我想在Rails 3应用程序中记录当前的回溯(stacktrace)而不会发生异常.知道怎么样?

我为什么要这个?我正在尝试跟踪Rails查找模板时所做的调用,以便我可以选择要覆盖的进程的一部分(因为我想更改我的特定子类控制器的视图路径).

我想从文件中调用它:gems\actionpack-3.2.3\lib\action_dispatch\middleware\templates\rescues\missing_template.erb.我知道这不是最佳实践,但我知道它是堆栈的下游,从那里搜索模板.

KL-*_*L-7 174

你可以使用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
Run Code Online (Sandbox Code Playgroud)

输出:

caller.rb:8:in `bar'
caller.rb:12:in `baz'
caller.rb:15:in `<main>'
Run Code Online (Sandbox Code Playgroud)

  • 不,从技术上讲,"调用者"是一种实例方法.由于`Kernel`模块包含在每个Ruby类中(1.9中的`BasicObject`除外),因此它可用作任何对象的实例方法(尽管它是私有的).您不能将其称为"Kernel.new.caller",因为您无法实例化模块(它没有`new`方法). (7认同)
  • 对于漂亮的打印使用 - "Rails.logger.debug caller.join("\n")`或`puts caller.join("\n")`.谢谢. (6认同)

小智 15

尝试使用

Thread.current.backtrace
Run Code Online (Sandbox Code Playgroud)

  • 这个答案的优点是它在回溯中包含**当前方法**,而“Kernel#caller”则省略了当前方法。例如 `MyClass.new.returns_caller =&gt; ["(irb):42:in 'irb_binding'",...]` 不如 `MyClass.new.returns_thread_backtrace =&gt; ["(irb):38:在'backtrace'中”,“(irb):38:在'returns_thread_backtrace'中”,“(irb):43:在'irb_binding'中”,...]` (4认同)

Ste*_*pis 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
Run Code Online (Sandbox Code Playgroud)