2014-07-09 68 views
2

寶石項目符號表示當爲加載到頁面的每餐食品加載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部分渲染線..

有趣的是,如果我有earger裝在部分子彈給我錯誤「未使用的急切加載!」並且第一食物中的膳食食物不正確地被帶到剩餘的膳食中。

這種方法看起來是這樣的:

內_meal.html.erb ...

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

將您的'@ meals'變量改爲'current_client.meals.includes(:meal_food)' – CWitty

+0

因爲'@ meals'沒有'。meals'('meal_food)'run' 1'查詢得到飯菜...在每一個部分(這一行特別是'meal.meal_foods')它運行** 1查詢你有每餐** ...所以如果你有'n'餐你跑'1'查詢來獲得所有的飯菜和'n'查詢來獲得每頓飯.meal_food('n + 1')...如果你使用'includes(:meal_food)' **它只運行一個優化的查詢來獲得他們的膳食食物關係加載的餐點** ...請等待@CWitty寫出答案並標記它:D –

+0

哦......它檢索每餐和他們的腐蝕性餐食在一個查詢中?很酷。另外,爲什麼我的評論被刪除? CWitty值得首先回答。我猜誰寫官方回答我的問題與此信息將得到信用。 –

回答

5

更改@meals變量是current_client.meals.includes(:meal_food)。正如@artimees所說,這種渴望加載數據並防止n + 1查詢。它的工作原理是@meals沒有.includes(:meal_food)運行1個查詢來獲得餐食......並且在每一個部分(這一行特別是meal.meal_foods)中它運行1個查詢你有每餐...所以如果你(n + 1)...如果你使用includes(:meal_food),它只運行一個優化的查詢來獲得他們的飯菜加載餐食關係...

+1

老兄來吧...複製解釋並獲得代表。你應得的。 –

+0

複製,歡呼! – CWitty