【发布时间】:2014-08-30 20:01:03
【问题描述】:
gem 项目符号表示我在为加载到页面的每种膳食食物加载 meal_foods 时出现 N + 1 错误。让我解释一下……
在我的 rails 应用程序中,我有一些嵌套的部分渲染如下:
膳食 > 膳食食品..
因此渲染了多餐,然后对于渲染的每一餐,如果有的话,相应的餐食也会在其中渲染。
这是代码。
用餐/表演内:
<% if @meals != nil %>
<%= render(partial: "meal", collection: @meals) %>
<% else %>
<p style="text-align:center">No meals created yet.</p>
<% end %>
这里是 _meals.html.erb
<tbody>
<%= render(partial: "meal_foods/meal_food", collection: meal.meal_foods) %>
</tbody>
最后这是 _meal_foods.html.erb 的一部分
<td class="left"><%= meal_food.name %></td>
<td class="left">
<%= form_for meal_food, action: :update do |f| %>
<%= f.text_field :servings %>
<% end %>
</td>
膳食控制员:
def show
@meals = current_client.meals
@new_meal = current_client.meals.build
end
具体错误:
N+1 Query detected
Meal => [:meal_foods]
Add to your finder: :include => [:meal_foods]
N+1 Query method call stack
/app/views/meals/_meal.html.erb:23:in
此错误指向的行是 _meal.html.erb 部分的渲染行..
有趣的是,如果我在该部分项目符号中包含预加载,则会出现错误“未使用预加载!”并且第一种食物中的膳食食物被错误地转移到其余的膳食中。
这个方法看起来像这样:
在 _meal.html.erb...
<tbody>
<% mf = MealFood.includes(:meal) %>
<%= render(partial: "meal_foods/meal_food", collection: mf) %>
</tbody>
【问题讨论】:
-
将您的
@meals变量更改为current_client.meals.includes(:meal_food) -
它起作用了,因为没有
.includes(:meal_food)的@meals运行1查询来获取餐点......并且在每个部分(特别是这一行meal.meal_foods)它运行1 个查询每顿饭...所以如果您有n餐点,则运行1查询以获取所有餐点,并运行n查询以获取每顿饭.meal_food (n+1)...如果您使用includes(:meal_food)它只运行一个优化查询来获取加载了他们的膳食食物关系的膳食...请等待@CWitty 写下答案并标记它:D -
Ohhh.. 它在一个查询中检索每餐及其对应的餐食?很酷。还有,为什么我的评论被删了? CWitty 的回答值得称赞。我猜谁用这些信息写官方回答我的问题都会得到荣誉。
-
没有@CWitty 是值得称赞的人
-
我现在添加它,谢谢:)
标签: ruby-on-rails ruby-on-rails-4 eager-loading partials