Ruby on rails 轨道4:小N+;未缓存页面的1个问题

Ruby on rails 轨道4:小N+;未缓存页面的1个问题,ruby-on-rails,Ruby On Rails,我有一个生成N+1数据库查询问题的代码 该问题仅在页面未缓存时发生。缓存页面后,添加.includes实际上会导致不必要的数据库调用。我想知道如何避开这个问题 myApplication on_helper.rb包含以下内容: module ApplicationHelper def by(article) "By #{article.username} on #{article.created_at.strftime('%B %e, %Y')}" end end class

我有一个生成N+1数据库查询问题的代码

该问题仅在页面未缓存时发生。缓存页面后,添加
.includes
实际上会导致不必要的数据库调用。我想知道如何避开这个问题

myApplication on_helper.rb包含以下内容:

module ApplicationHelper
  def by(article)
    "By #{article.username} on #{article.created_at.strftime('%B %e, %Y')}"
  end
end
class ArticlesController < ApplicationController
  def index
    @articles = user_signed_in? ? Article.all.includes(:user) : Article.all.published.limit(13).includes(:user)
  end
end
myarticle.rb包含:

class Article < ActiveRecord::Base
  belongs_to :user

  def username
    user.username
  end
end
class ArticlesController < ApplicationController
  def index
    @articles = user_signed_in? ? Article.all : Article.all.published.limit(13)
  end
end
N+1问题在第一次加载页面时消失,但在重新加载页面时,我会得到一个不必要的
。includes

你知道我该怎么解决这个小问题吗


谢谢

我找到了一个疯狂的解决方案:您可以检查控制器中是否存在缓存片段。但问题是Rails会自动将文件摘要添加到缓存密钥中。所以,我的“解决方案”:像这样将缓存方式更改为smth

# in your view:
<% cache 'foo', skip_digest: true do %>
  contents
<% end %>
显然,关闭摘要不是很好的解决方案:在解决当前问题的同时,它会增加一个新的问题。但它是有效的:)


我找不到在控制器中获取视图摘要的方法,但无论如何,我认为对于一次出现N+1这样一个小问题来说,这太过分了。如果困扰你的仅仅是
bullet
警告,你可以采取特定的行动。

不知何故,这解决了我的问题:

class Article < ActiveRecord::Base
  belongs_to :user
  delegate :username, to: :user
end
类文章

因此,我只需将文章的用户名调用委托给用户模型。漂亮、干净,而且很管用:子弹不再抱怨了。

这真的没有意义<代码>包含
应使用一个查询加载用户。可能还有别的事情。您是否启用了开发中的缓存来测试这一点?我觉得这就像是
文章。username
调用通过附加请求在模型中查找这一点。@Mohamad我刚刚禁用了开发中的缓存。我现在一直从Bullet收到一条消息,说
N+1查询检测到的文章=>[:user]Add to your finder::includes=>[:user]N+1查询方法调用堆栈~/myapp/app/models/Article.rb:64:in`username'
我可以确认,将
.includes(:user)
添加到我的控制器中可以清除该消息(禁用缓存)。重新启用缓存会导致以下消息:
Unused Eager Loading detected Article=>[:user]Remove from your finder::includes=>[:user]
…令人难以置信@在我看来,日志意味着:调用
Article.user.username
而不是
Article.username
,它指向
username
方法。谢谢。实际上,我认为问题可能出在Bullet上,而不是使用
.includes(:user)
。我会报告,看看他们怎么想。对我来说,
bullet
在这种情况下是正确的,因为当页面被缓存时,
includes
确实是不必要的。但是既然你知道它,而且它是你想要的行为,你可以把警告关掉。
class Article < ActiveRecord::Base
  belongs_to :user
  delegate :username, to: :user
end