예외를 발생시키지 않고 Ruby에서 현재 스택 추적을 가져옵니다.


139

예외가 발생 하지 않고 Rails 3 앱에 현재 역 추적 (stacktrace)을 기록하고 싶습니다 . 어떻게 생각해?

왜 이것을 원합니까? Rails가 템플릿을 찾을 때 수행되는 호출을 추적하려고합니다. 내가 특정 하위 클래스 컨트롤러의 뷰 경로를 변경하고 싶기 때문에 재정의 할 프로세스의 일부를 선택할 수 있습니다.

파일에서 호출하고 싶습니다 : 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여기에 정의되어 있지 않습니다
ecoologic

8
아니요, 기술적 caller으로 인스턴스 방법입니다. Kernel모듈은 모든 Ruby 클래스 ( 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"). 감사.
Jignesh Gohel

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.