2014-07-09 39 views
1

我有一個N + 1問題,我無法解決。我這裏主持一個示例應用程序,顯示問題:https://github.com/davidmles/question_parts更新與關係的模型時N + 1問題

這是它如何工作的:

車型有4款:問題,question_part,接聽和answer_part。 一個問題有N個部分,還有N個答案。答案有N個部分。答案部分屬於答案和問題部分(答案部分)。

答案可以是草稿或已發佈。草稿不需要全部回答,公佈的答案確實需要他們回答。

問題:

當答案被創建,但不是所有的部件都回答了,我嘗試發佈它,驗證將失敗,並編輯表單將再次顯示。在驗證失敗之後顯示編輯表單時,將出現N + 1問題,因爲答案部分將加載相應的問題部分而無需加載它們。

我試圖急於加載它們,但編輯表單不會顯示正確的錯誤。

我該如何解決這個問題?我在應用程序的自述文件中添加了更多信息,並在查看問題時指導了以下步驟:https://github.com/davidmles/question_parts/blob/master/README.md

+0

您是否在應用程序中添加了子彈寶石? – Icicle

+0

https://github.com/davidmles/question_parts/blob/master/Gemfile#L43 –

回答

3

壞消息:看起來ActiveRecord在集合關聯中與#includes不搭配。而實際上你不能破解它,因爲它不會保留關係對象(here)。

好消息:我找到了一些解決方法。

has_many :question_parts, through: :parts添加到您的答案模型。之後,在answers_controller中使用此查找器:@answer = Answer.preload(:question_parts).where(id: params[:id]).first。有時子彈寶石不喜歡這樣(它說未使用急切加載blabla,但它不是這樣),但沒有N + 1查詢和表單工作正常。

+0

+1,爲你接受答案和賞金:) –

1

只是爲了補充閃登的答案,查詢也可以寫成這樣:

@answer = Answer.preload(parts: [:question_part]).where(id: id).first 

所以,不需要修改Answer

此外,使用includes代替preload似乎工作(Rails在此情況下選擇正確的策略)。