如何在请求之间缓存实例变量?

时间:2014-03-22 01:23:28

标签: ruby-on-rails

Miniprofiler表明我的Rails应用程序正在每个页面上进行大量的数据库查询。问题似乎是布局中包含的排行榜模块。

应用程序如下所示:

#application_controller.rb
before_filter :initialize_leaderboard

def initialize_leaderboard
  @leaderboard_users ||= User.monthly_leaderboard
end

#user.rb

def self.monthly_leaderboard
  User.includes(:events).sort_by(&:events_last_month).reverse
end

def events_last_month
  @events_last_month ||= events.where( created_at: Date.today.beginning_of_month-1.month..Date.today.end_of_month-1.month ).size
end

#application.html.erb
...
<% unless @leaderboard_users.blank? %>
  <% cache ["sidebar_leaderboard", @leaderboard_users] do %>
    ...html
  <% end %>
<% end %>

在日志和miniprofiler输出中,我看到每个用户都有events_last_month个查询。这不太令人满意,并让我质疑我对这一切是如何运作的理解。我这样做了吗?

  1. 视图已缓存,因此只要具有特定的leaderboard_user即可 已被浏览过(最近),他的详细信息应该显示出来 来自缓存。
  2. 因此,许多events_last_month查询必须来自 application_controller.rb中的initialize_leaderboard方法。但是我 明白使用||=会缓存响应 后续请求的User.monthly_leaderboard方法。为什么 在每个页面视图上调用?

1 个答案:

答案 0 :(得分:4)

||=会记住来自User.monthly_leaderboard的非虚假结果。该数据将在ApplicationController实例的生命周期内保留。为每个请求创建一个新实例。

From the docs:

  

当您的应用程序收到请求时,路由将确定   要运行哪个控制器和操作,然后Rails创建一个实例   该控制器并运行与操作同名的方法。

如果您希望缓存(偶尔会过期并重新查询)该实例变量的值,您需要explicitly utilize an external cache之间的请求,或者找到另一个地方来存储在会话等请求中持续存在的值结果相对较小,并且特定于用户的会话。

如果它是一个应该被查询的值并且一直存在直到重新启动Web服务器,那么考虑在初始化程序中查询该数据并将结果存储在将在该过程的整个过程中持续存在的地方。