アプリの各ページでレンダリングされたパーシャルを一覧表示したいと考えています。たとえば、app/tasks/index.html.erb ページが表示されている場合、次のような内容をユーザーに表示したいと思います。
このページ用にレンダリングされたパーシャル:
タスク/_list.html.erb
タスク/_button.html.erb
タスク/_navigation.html.erb
Ruby on Railsでこれを行う方法はありますか?
アプリの各ページでレンダリングされたパーシャルを一覧表示したいと考えています。たとえば、app/tasks/index.html.erb ページが表示されている場合、次のような内容をユーザーに表示したいと思います。
このページ用にレンダリングされたパーシャル:
タスク/_list.html.erb
タスク/_button.html.erb
タスク/_navigation.html.erb
Ruby on Railsでこれを行う方法はありますか?
はい、Rails でこれを行う完全な方法があります。
bdares がコメントで指摘したように、テンプレート レンダリングの行がログに表示されます。しかし、そもそもどうやってそこにたどり着くのでしょうか? それは、Active Support の と呼ばれるちょっとしたものとLogSubscriber
関係があります。これに関するドキュメントはかなり完全です:
ActiveSupport::LogSubscriber は、ActiveSupport::Notification をログに記録することのみを目的として消費するように設定されたオブジェクトです。ログ サブスクライバーは、指定された名前空間に基づいて登録済みオブジェクトに通知をディスパッチします。
ログに「Rendered ...」行を入れているのは、Rails 3.2 内でこのようにActionView::LogSubscriber
定義されていることです。コードを読んでみてください。それは素晴らしく、きれいです。
render_template
これが行っているのは、Rails 内のいくつかのイベント、つまりrender_partial
とrender_collection
メソッドをサブスクライブすることです。ActiveSupport::LogSubscriber.attach_to
これは、いくつかのイベントにログ サブスクライバーをアタッチするメソッドを呼び出すことによって行われます。このメソッドも興味深いもので、次のように定義されています。
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
このコードは私たちの関心に非常に関連しているため、このコードを記載しました。subscribe
これが行っているのは、notifier
オブジェクトの呼び出しです。notifier
オブジェクトはデフォルトで です。ActiveSupport::Notifications
これは覚えておくことが重要です。Rails のそのクラスのドキュメントも API にあります。
がsubscribe
呼び出されると、 の名前を通過しevent
ます。これは何ですか?まあ、それはクラス内のすべてのパブリック メソッドです。LogSubscriber
サブクラスが定義されると、いくつかのパブリック メソッドが定義されます: render_template
、render_partial
およびrender_collection
。これらは、このログ サブスクライバーに対してサブスクライブされるイベントです。
同じものを使用してビュー内のこれらのイベントをサブスクライブするため、これは私たちの興味に関連しています。最初のステップは、すべての部分レンダリング イベントActiveSupport::Notfications
をサブスクライブできるようにすることです。内に新しいを作成することでこれを行うことができます:before_filter
ApplicationController
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
サブスクライブしているイベントは、名前空間render_partial
内のイベントであり、サブスクライブしているイベントの 1 つです。パーシャルがレンダリングされると、このブロックが呼び出されてデータが渡されます。action_view
ActionView::LogSubscriber
event_name
: イベントの名前。
start_at
: イベントの開始時刻。
end_at
: イベントが終了した時刻。
id
: このイベントの一意の識別子。
payload
: このイベントに関する一部のペイロード情報。
フックが呼び出されると、メソッドの先頭で定義された配列にidentifier
キーが追加されます。payload
次に、ビューでこれらのリストにアクセスするには、次のようにします。
<%= debug @partial_events %>
次のNotification APIの例が役に立ちます。
ActiveSupport::Notifications.subscribe("render") do |*args|
events << ActiveSupport::Notifications::Event.new(*args)
end
あなたのケース(レンダリングされたパーシャルの追跡)では、'render_partial.action_view'
通知が必要です。コードは次のようになります。
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
この情報を表示したい場合は、次のヘルパー メソッドを使用できます。
def display_render_events
raw(@render_events.map do |event|
event.payload[:identifier].gsub(/^.*app\/views\//, '')
end.join('<br/>'))
end
このような多くのデバッグ情報については、rails-footnotesをご覧ください。
Chrome拡張機能であるRailsPanelを確認することもできます。