渴望从嵌套的部分加载

时间:2014-07-09 17:02:46

标签: ruby-on-rails ruby-on-rails-4 eager-loading partials

宝石子弹说我在为每个加载到页面的食物加载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 partial ..

的渲染行

有趣的是,如果我在部分子弹中包含了一个加载器,那就会给我一个错误&#34;未使用的急切加载!&#34;并且第一食物中的膳食食物也被错误地转移到其余的食物中。

此方法如下所示:

在_meal.html.erb ...

<tbody>
  <% mf = MealFood.includes(:meal) %>
  <%= render(partial: "meal_foods/meal_food", collection: mf) %>
</tbody>

1 个答案:

答案 0 :(得分:5)

@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)它只运行一个优化的查询来获得他们的饭菜饭菜关系加载...