Nic*_*Res 2 ruby-on-rails partials eager-loading ruby-on-rails-4
宝石子弹说我在装载到页面的每餐食物加载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 %>
Run Code Online (Sandbox Code Playgroud)
这是在_meals.html.erb中
<tbody>
<%= render(partial: "meal_foods/meal_food", collection: meal.meal_foods) %>
</tbody>
Run Code Online (Sandbox Code Playgroud)
最后,这是_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>
Run Code Online (Sandbox Code Playgroud)
膳食控制器:
def show
@meals = current_client.meals
@new_meal = current_client.meals.build
end
Run Code Online (Sandbox Code Playgroud)
具体错误:
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
Run Code Online (Sandbox Code Playgroud)
此错误指向的行是_meal.html.erb部分的渲染行.
有趣的是,如果我在部分子弹中加入了管理器加载,则会给出错误"未使用的急切加载!" 并且第一食物中的膳食食物也被错误地转移到其余的食物中.
此方法如下所示:
在_meal.html.erb中......
<tbody>
<% mf = MealFood.includes(:meal) %>
<%= render(partial: "meal_foods/meal_food", collection: mf) %>
</tbody>
Run Code Online (Sandbox Code Playgroud)
将@meals变量更改为current_client.meals.includes(:meal_food).正如@artimees所说,这种渴望加载数据并阻止n + 1查询.它之所以有效,是因为没有.includes(:meal_food)的@meals运行1个查询来获取餐点......并且在每个部分(这一行特别是meal.meal_foods)中,它为您的每餐提供1个查询...所以如果你有n餐你运行1查询得到所有的饭菜和n查询来获得每餐.meal_food(n + 1)...如果你使用包括(:meal_food)它只运行一个优化的查询来获得他们的饭菜饭菜关系装...