【问题标题】:Reporting data from view in rails after_filter从 rails after_filter 中的视图报告数据
【发布时间】:2012-10-12 16:13:28
【问题描述】:

我想在我的视图中记录某些块的缓存未命中数。我将日志存储在控制器的 after_filter 中。

在视图中操作实例变量似乎是不可能的。在视图渲染期间存储信息然后提供给控制器的 after_filter 的最佳方式是什么?

【问题讨论】:

  • 我希望最终缓存未命中可以通过模型记录到某个地方,为什么不让模型处理这个,让模型作为中间人,在两者之间保存数据,控制器和视图都可以随时访问.
  • 以线程安全的方式将这些数据保存在模型中是否容易?缓存未命中统计信息似乎应该从模型逻辑中删除,因为它们仅与视图呈现本身相关(这是缓存的 HTML)。
  • 您是否已经发现任何线程问题?与所有 cmets 一样,您似乎对线程安全感到担忧。
  • 我之前在模型中存储控制器数据时遇到过线程问题,使用Thread.current[] 构造解决了。
  • (我应该指出这通常是一件坏事,但有时您的问题不适合 MVC 分离,不值得强制该模型)

标签: ruby-on-rails ruby-on-rails-3


【解决方案1】:

不确定这是否是最佳解决方案,但它适用于测试 Rails 应用程序:

向你的控制器添加一个方法。它必须是公开的,除非你可以使用send 调用它。

def increment_miss
  @miss_count ||= 0
  @miss_count += 1
end

然后是 after_filter(我已将我的限制为 :index):

after_filter :only => :index do
  Rails.logger.info("miss_count: #{@miss_count.to_i}")
end

然后根据需要多次调用视图中的方法:

<% controller.increment_miss %>

如果您希望每次调用能够增加 1 以上,您可能需要修改该方法以采用可选的 increment_by 参数。

【讨论】:

  • 你知道这如何与线程交互吗? @miss_count 会在该应用实例上运行的所有线程之间共享,还是在请求本地?
  • @miss_count 是为当前请求提供服务的线程的本地变量,就像任何其他控制器实例变量(例如那些用于存储要传递给视图的对象的变量)一样。 Rails 为每个请求创建一个新的控制器实例。
  • 这对我来说很有意义。在我有机会在接下来的几天内实施它后,我会回来并接受它。感谢您的帮助。
  • 视图操作仅停留在视图中,抱歉 Kelvin,这不起作用。
  • @AmolPujari 这仅适用于视图所做的某些更改,例如设置实例变量。但是,如果视图调用改变控制器状态的方法,则该更改将持续存在并可供after_filter 使用。你真的试过代码吗?
【解决方案2】:

我会考虑将逻辑移动到专用模型对象中。

class MyController > ApplicationController
  around_filter :record_cache_misses

  def record_cache_misses
    @cache_miss_logger = CacheMissLogger.new
    yield
    @cache_miss_logger.persist_count
  end
end

在视图中这将是一个正常的方法调用。

<% @cache_miss_logger.increment_count %>

【讨论】:

  • 创建一个单独的类来保存值似乎有点过头了。为什么这样做而不是 @kelvin 的实例变量思想?
  • 嗨斯派克。另一个答案也可以。这是一个偏好问题。我认为我仍然深受 Avdi Grimm 的 Objects on Rails 书籍的影响,其中强调小型、单一职责的类。
  • 根据 persist_count 所做的事情,可能存在竞争条件。不过,仅写入日志应该不是问题。
【解决方案3】:

我建议,

  1. 没有直接的方法来实现这一点,因为它不是每个 rails MVC 规则,并且无论如何它是不可行的(除非你改变 rails)

  2. 您处理范围从视图开始和结束的数据,那么为什么要反转并让控制器负责记录/使用它,让视图/帮助方法记录它

  3. 所以你可以在控制器中启动它,你可能在控制器中引用了缓存,把它向前推进,让视图操作它,在视图/帮助器中你可以记录它,保留一个单独的日志存储模块/文件照顾这个问题,让助手包含它,从视图中调用它。

【讨论】:

  • 当然,您可以将其设为辅助方法,但您必须确保在 完成计数后在视图中调用它 all 缓存未命中。这使得它非常脆弱,因为每次向需要增加计数器的视图文件添加新代码时,您必须记住将方法调用进一步向下移动。它与局部更令人困惑。
  • 布局中的页脚后应该有一个空格
【解决方案4】:

我找到了另一种出路,我希望/猜想它是线程安全的,如果有人确认会很棒

# in controller
before_filter :foo
after_filter :bar

def foo
  class << @cache_miss
    attr_accessor :count
  end

  @cache_miss.count = 1
  puts "----------#{@cache_miss.count}" # => 1
end

def bar
  puts "----------#{@cache_miss.count}" # => 2
end

#in views
<% @cache_miss.count = 2 %>

【讨论】:

  • 你在哪里分配@cache_miss?如果您不分配它,您会将单例访问器添加到全局 nil 对象。此外,只有将其设置为未共享的对象时,它才会是线程安全的。你可以使用OpenStruct
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-27
相关资源
最近更新 更多