Nhận theo dõi ngăn xếp hiện tại trong Ruby mà không đưa ra một ngoại lệ


138

Tôi muốn đăng nhập backtrace hiện tại (stacktrace) trong ứng dụng Rails 3 mà không có ngoại lệ xảy ra. Có ý kiến ​​gì không?

Tại sao tôi muốn điều này? Tôi đang cố gắng theo dõi các cuộc gọi được thực hiện khi Rails tìm kiếm một mẫu để tôi có thể chọn một phần của quy trình để ghi đè (vì tôi muốn thay đổi đường dẫn xem cho một bộ điều khiển phân lớp cụ thể của tôi).

Tôi muốn gọi nó từ tập tin : gems\actionpack-3.2.3\lib\action_dispatch\middleware\templates\rescues\missing_template.erb. Tôi biết đó không phải là cách thực hành tốt nhất, nhưng tôi biết đó là hạ lưu của ngăn xếp từ nơi tìm kiếm mẫu xuất hiện.


4
Giải pháp bẩn: nêu ra một ngoại lệ ở đó, giải cứu nó ngay lập tức và đăng nhập e.backtrace. Tôi đã thấy nó trong một trong những dự án tôi đang làm việc. Không phải là cách tiếp cận đẹp nhất, nhưng nó hoạt động. Dù vậy, hy vọng được nghe một giải pháp tốt hơn từ người khác.
KL-7

Câu trả lời:


185

Bạn có thể sử dụng 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

Đầu ra:

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

Có phải vậy không Kernel.caller- với một dấu chấm? Kernel.new.callerkhông được xác định ở đây
ecoologic

8
Không, về mặt kỹ thuật callerlà một phương pháp ví dụ. Vì Kernelmô-đun được bao gồm trong mọi lớp Ruby (ngoại trừ BasicObject1.9), nên nó có sẵn dưới dạng phương thức cá thể trên bất kỳ đối tượng nào (mặc dù nó là riêng tư). Bạn không thể gọi nó Kernel.new.callerđơn giản vì bạn không thể khởi tạo một mô-đun (nó không có newphương thức).
KL-7

cái này hỗ trợ một tham số để bỏ qua bất kỳ số lượng người gọi nào; xem: stackoverflow.com/a/3829269/520567
akostadinov

7
Để sử dụng in đẹp - Rails.logger.debug caller.join("\n")hoặc puts caller.join("\n"). Cảm ơn.
Jignesh Gohel

20

Hãy thử sử dụng

Thread.current.backtrace

1
Ưu điểm của câu trả lời này là nó bao gồm phương thức hiện tại trong backtrace, trong khi Kernel#callerbỏ qua phương thức hiện tại. Ví dụ: MyClass.new.returns_caller => ["(irb):42:in 'irb_binding'",...] không hữu ích như MyClass.new.returns_thread_backtrace => ["(irb):38:in 'backtrace'","(irb):38:in 'returns_thread_backtrace'","(irb):43:in 'irb_binding'",...]
stwr667

6

Tôi sử dụng điều này để hiển thị một trang lỗi tùy chỉnh khi ngoại lệ được đưa ra.

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.