Отримайте поточний слід стеку в Ruby, не збільшуючи виняток


139

Я хочу записати поточний заднім числом (стек-трек) у додатку Rails 3 без винятку. Будь-яка ідея як?

Чому я хочу цього? Я намагаюся простежити виклики, які виконуються, коли 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.