2013-03-18 3 views
7

Ich möchte die Teiltöne für jede Seite in meiner App auflisten. Zum Beispiel, wenn die app/Aufgaben/index.html.erb Seite gezeigt wird, würde Ich mag so etwas wie die folgenden, um den Benutzer anzuzeigen:Ruby on Rails: Wie listen Sie die Teilpfade auf, die für eine Seite gerendert werden?

Partials für diese Seite gemacht:

Aufgaben/_list.html.erb
Aufgaben/_button.html.erb
Aufgaben/_navigation.html.erb

gibt es eine Möglichkeit, um auf Rails in Ruby zu tun?

ActiveSupport::Notifications.subscribe("render") do |*args| 
    events << ActiveSupport::Notifications::Event.new(*args) 
end 

Für Ihren Fall (Tracking gemacht partials) können Sie die 'render_partial.action_view' Benachrichtigung wünschen:

+0

Ich bin mir sicher, dass es einen Weg gibt, wenn man bedenkt, dass fast genau diese Zeilen in den Serverprotokollen gedruckt sind. Ich würde anfangen, den Middleware-Stack zu betrachten ... – bdares

+1

@bdares: Es ist nicht in der Middleware-Stack. Es ist ein Instrumentenruf. –

Antwort

15

Ja, es ist so ganz ein Weg, dies zu tun in Schienen!

Wie bdares in seinem Kommentar darauf hingewiesen hat, erscheinen die Zeilen für das Template-Rendering in den Protokollen. Aber wie kommen sie überhaupt dorthin? Nun, das hat mit einem little something in Active Support called LogSubscriber zu tun. Die Dokumentation dafür ist ziemlich gründlich:

ActiveSupport :: LogSubscriber ist ein Objekt, das ActiveSupport :: Notifications mit dem einzigen Zweck verwendet, sie zu protokollieren. Der Protokollteilnehmer sendet basierend auf seinem angegebenen Namespace Benachrichtigungen an ein registriertes Objekt.

Die Sache, die die „Übertragene ...“ Linien in den Protokollen ist setzen, ist ActionView::LogSubscriber die like this within Rails 3.2 definiert ist. Nimm dir einen Moment, um den Code zu lesen. Es ist nett und ordentlich.

Was dies tut, um ein paar Ereignisse innerhalb Rails abonniert, nämlich die render_template, render_partial und render_collection Methoden. Dazu wird die Methode ActiveSupport::LogSubscriber.attach_to aufgerufen, die einigen Ereignissen einen Protokollabonnenten anfügt. Das Verfahren ist auch interessant, und wie folgt definiert:

def attach_to(namespace, log_subscriber=new, notifier=ActiveSupport::Notifications) 
    log_subscribers << log_subscriber 
    @@flushable_loggers = nil 

    log_subscriber.public_methods(false).each do |event| 
    next if 'call' == event.to_s 

    notifier.subscribe("#{event}.#{namespace}", log_subscriber) 
    end 
end 

ich diesen Code in Zeile gesetzt habe, weil es unsere Interessenäußerst relevant ist. Was das tut, ruft subscribe auf dem notifier Objekt auf. Das Objekt notifier ist standardmäßig ActiveSupport::Notifications, was wichtig zu erinnern ist. Die documentation for that class in Rails is in the API too.

Wenn subscribe aufgerufen wird, wird der Name event übergeben. Was ist das? Nun, es ist jede einzelne öffentliche Methode in der Klasse.Wenn die Unterklasse LogSubscriber definiert ist, definiert sie ein paar öffentliche Methoden: render_template, render_partial und render_collection. Dies sind die Ereignisse, die für diesen Protokollteilnehmer abonniert werden.

Nun, das ist relevant für unsere Interessen, weil wir das gleiche verwenden werden, um diese Ereignisse in der Ansicht zu abonnieren. Der erste Schritt ist ActiveSupport::Notfications, dass wir alle partiellen Rendering-Ereignisse abonnieren möchten. Wir können dies tun, indem Sie einen neuen before_filter innerhalb ApplicationController erstellen:

before_filter :log_partial_events 

def log_partial_events 
    @partial_events = [] 
    ActiveSupport::Notifications.subscribe("render_partial.action_view") do |event_name, start_at, end_at, id, payload| 
    @partial_events << payload[:identifier] 
end 

Die Veranstaltung wir sind der abonnieren möchte die render_partial Ereignis innerhalb des action_view Namensraum ist, der genau eines der Ereignisse, die ActionView::LogSubscriber zu abonniert. Was passiert, wenn ein Partial gerendert wird, ist, dass dieser Block in einigen Daten aufgerufen und übergeben wird.

event_name: Der Name des Ereignisses. start_at: Die Zeit, zu der das Ereignis begann. end_at: Die Zeit, zu der das Ereignis endete. id: Eine eindeutige ID für dieses Ereignis. payload: Einige Nutzinformationen zu diesem Ereignis.

Wenn der Hook aufgerufen wird, fügt er den identifier Schlüssel aus dem payload dem Array hinzu, das am Anfang der Methode definiert ist.

Dann in der Ansicht, eine Liste dieser zuzugreifen, dies zu tun:

<%= debug @partial_events %> 
+2

Das ist wunderbar, Ryan! Es hat perfekt funktioniert. Danke für deine unglaublich klare Anleitung und Anleitung! :) – sjsc

+0

Super Antwort Ryan, danke! –

+0

Toller Tipp, danke! Vorschlag: Eine Einrückung des Blocks in Ihrem Beispiel oder eine Closing-End-Anweisung für die Methodendefinition könnte es klarer machen, was vor sich geht. – alegscogs

4

Das folgende Beispiel aus dem Notification API sollte Ihnen helfen. Der Code könnte wie folgt aussehen:

class ApplicationController < ActionController::Base 
    before_filter :subscribe_to_render 

    private 
    def subscribe_to_render 
    @render_events = [] 
    ActiveSupport::Notifications.subscribe("render_partial.action_view") do |*args| 
     @render_events << ActiveSupport::Notifications::Event.new(*args) 
    end 
    end 
end 

und wo immer Sie diese Informationen angezeigt werden möchten, können Sie diese Hilfsmethode verwenden:

def display_render_events 
    raw(@render_events.map do |event| 
    event.payload[:identifier].gsub(/^.*app\/views\//, '') 
    end.join('<br/>')) 
end 
+1

Lustig, dass wir einen sehr ähnlichen Ansatz zur Lösung dieses Problems hatten. Großartige Gedanken und all das :) –

+2

@RyanBigg: Danke für die Bearbeitung :) Der Unterschied war, dass ich wirklich nach unten bohren musste, um es zu finden, während du wusstest, wo es die ganze Zeit war. – PinnyM

+0

Danke für den Link Pinny! Du und Ryan sind großartig :) – sjsc

2

Sie auch überprüfen möchten RailsPanel Dies ist eine Chrome-Erweiterung.

Verwandte Themen