我想列出我的应用程序中每个页面呈现的部分内容。例如,当显示app / tasks / index.html.erb页面时,我想向用户显示以下内容:
为此页面呈现的部分:
任务/ _list.html.erb 任务/ _button.html.erb 任务/ _navigation.html.erb
有没有办法在Ruby on Rails中这样做?
是的,在Rails中有这么完美的方法!
正如bdares在他的评论中指出的那样,模板渲染的线条出现在日志中。但是,他们如何在第一时间到达那里?嗯,这与little something in Active Support called LogSubscriber
有关。这方面的文档非常详尽:
ActiveSupport :: LogSubscriber是一个设置为使用ActiveSupport :: Notifications的对象,其唯一目的是记录它们。日志订阅者基于其给定的命名空间向已注册的对象分派通知。
在日志中放置“Rendered ...”行的是ActionView::LogSubscriber
,它定义为like this within Rails 3.2。花一点时间阅读代码。这很好,很整洁。
这样做是订阅Rails中的几个事件,即render_template
,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
,这一点很重要。 documentation for that class in Rails is in the API too。
当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
命名空间中的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
您可能还想查看RailsPanel这是一个Chrome扩展程序。
这是一个旧帖子,但万一有人发现这个有用的一个非常简单的方法来列出所有视图和部分用于你点击通过你的网站是重新启动你的服务器只有grep为“渲染”,例如
rails s | grep "Rendered"