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
个查询。这不太令人满意,并让我质疑我对这一切是如何运作的理解。我这样做了吗?
events_last_month
查询必须来自
application_controller.rb中的initialize_leaderboard
方法。但是我
明白使用||=
会缓存响应
后续请求的User.monthly_leaderboard
方法。为什么
在每个页面视图上调用?答案 0 :(得分:4)
||=
会记住来自User.monthly_leaderboard
的非虚假结果。该数据将在ApplicationController
实例的生命周期内保留。为每个请求创建一个新实例。
当您的应用程序收到请求时,路由将确定 要运行哪个控制器和操作,然后Rails创建一个实例 该控制器并运行与操作同名的方法。
如果您希望缓存(偶尔会过期并重新查询)该实例变量的值,您需要explicitly utilize an external cache之间的请求,或者找到另一个地方来存储在会话等请求中持续存在的值结果相对较小,并且特定于用户的会话。
如果它是一个应该被查询的值并且一直存在直到重新启动Web服务器,那么考虑在初始化程序中查询该数据并将结果存储在将在该过程的整个过程中持续存在的地方。