Özel durum oluşturmadan Ruby'de mevcut yığın izlemesini alın


139

Bir istisna olmadan Rails 3 uygulamasında geçerli geri izleme (stacktrace) günlüğe kaydetmek istiyorum . Nasıl olduğu hakkında bir fikrin var mı?

Bunu neden istiyorum? Ben (örneğin belirli bir alt sınıflı denetleyicimin görünüm yolunu değiştirmek istiyorum) geçersiz kılmak için sürecin bir bölümünü seçebilirsiniz Rails bir şablon arar yapılan çağrıları izlemeye çalışıyorum.

Ben dosyadan çağırmak istiyorum: gems\actionpack-3.2.3\lib\action_dispatch\middleware\templates\rescues\missing_template.erb. Bunun en iyi uygulama olmadığını biliyorum, ancak şablon aramasının yapıldığı yerin akış aşağısında olduğunu biliyorum.


4
Kirli çözüm: Orada bir istisna oluşturun, hemen kurtarın ve oturum açın e.backtrace. Çalıştığım projelerden birinde gördüm. En iyi yaklaşım değil, ama işe yarıyor. Yine de birinden daha iyi bir çözüm duymayı umuyoruz.
KL-7

Yanıtlar:


185

Şunları kullanabilirsiniz 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

Çıktı:

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

Kernel.callerBir nokta ile değil mi? Kernel.new.callerburada tanımlanmamıştır
ecoologic

8
Hayır, teknik callerolarak bir örnek yöntemdir. Yana Kernelmodülü (dışında her Ruby sınıfına dahil olup BasicObject, 1.9 olarak), (o da, özel s) herhangi bir nesne üzerinde örnek yöntemi olarak kullanılabilir. Kernel.new.callerBir modülü başlatamadığınız için bu newyöntemi çağıramazsınız ( yöntemi yoktur).
KL-7

bu, herhangi bir sayıda arayanı atlamak için bir parametreyi destekler; bkz. stackoverflow.com/a/3829269/520567
akostadinov

7
Güzel baskı kullanımı için - Rails.logger.debug caller.join("\n")veya puts caller.join("\n"). Teşekkürler.
Jignesh Gohel

20

Kullanmayı deneyin

Thread.current.backtrace

1
Bu cevabın avantajı , geri izlemedeki geçerli yöntemi içermesi ve geçerli yöntemi bırakmasıdır Kernel#caller. Örneğin MyClass.new.returns_caller => ["(irb):42:in 'irb_binding'",...] , çok yararlı değil MyClass.new.returns_thread_backtrace => ["(irb):38:in 'backtrace'","(irb):38:in 'returns_thread_backtrace'","(irb):43:in 'irb_binding'",...]
stwr667

6

İstisna ortaya çıktığında özel bir hata sayfası göstermek için bunu kullanıyorum.

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.