是的,在 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
我已将这段代码放在一行中,因为它与我们的兴趣非常相关。这样做是在 notifier 对象上调用 subscribe。 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 我们想要订阅all 部分渲染事件。我们可以通过在ApplicationController 中创建一个新的before_filter 来做到这一点:
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
我们订阅的事件是action_view 命名空间中的render_partial 事件,这正是ActionView::LogSubscriber 订阅的事件之一。当一个部分被渲染时会发生什么,这个块将被调用并传入一些数据。
event_name:事件的名称。
start_at:活动开始的时间。
end_at:活动结束的时间。
id:此事件的唯一标识符。
payload:有关此事件的一些有效负载信息。
当调用钩子时,它会将identifier 中的identifier 键添加到方法顶部定义的数组中。
然后在视图中,要访问这些列表,您可以这样做:
<%= debug @partial_events %>