我使用bullet gem找出我的应用有哪些n + 1查询问题,结果发现我有3个问题:
用户:检测到Rashed N + 1查询Sale => [:shop]加入你的发现者: :includes => [:shop]用户:检测到Rashed N + 1查询Shop => [:商场] 添加到您的finder :: includes => [:malls] user:Rashed N + 1 Query 检测到Shop => [:categories]添加到您的finder :: includes => [:类别]
问题是我不确定如何使用包含解决问题,因为我的模型与彼此相关联。我有4个型号,销售,商店,商城和类别。这些是我的模型的关联:
class Shop < ActiveRecord::Base
has_many :categorizations
has_many :categories, :through => :categorizations
has_many :mall_shops
has_many :malls, :through => :mall_shops
has_many :sales, dependent: :destroy
end
class Sale < ActiveRecord::Base
belongs_to :shop
end
class Mall < ActiveRecord::Base
has_many :mall_shops
has_many :shops, :through => :mall_shops
has_many :sales, :through => :shops
end
class Category < ActiveRecord::Base
has_many :categorizations
has_many :shops, :through => :categorizations
has_many :sales, :through => :shops
end
在我的销售索引页面中,我显示所有销售记录,每个销售记录属于一个商店,每个商店有许多类别和许多商场。对于显示的每个销售记录,我都会遍历Sale&Shop的商店所属的所有商场和类别(用于过滤目的)。这是我的销售索引页面中的相关代码:
<% @sales.each do |sale| %>
<div class="<% sale.shop.malls.each do |m| %> mall<%= m.id %><% end %><% sale.shop.categories.each do |c| %> category<%= c.id %><% end %>">
.
.
end
我的销售总监:
class SalesController < ApplicationController
def index
@malls = Mall.all.order('name ASC')
@categories = Category.all.order('category_type ASC')
@shops = Shop.all
@sales = Sale.where('offer_end >= ?', Date.today).order('offer_end ASC')
end
end
那么解决我遇到的n + 1查询问题的最佳方法是什么?为了更好地了解我的应用程序,这是我建立的网站:www.shopwatchkw.com
答案 0 :(得分:3)
在控制器中,试试这个:
@sales = Sale.includes(shop: [:categories, :malls])
.where('offer_end >= ?', Date.today)
.order('offer_end ASC')
基本上,您从顶级模型开始,并通过includes
语句急切加载其子级。 Bullet告诉你添加.includes(:shop)
,之后,它可能会告诉你关于:categories
和:mails
的相同内容,它们是Shop上的子查询,正如你所描述的那样。