更新具有关系的模型时出现N + 1问题

时间:2014-07-09 12:30:31

标签: ruby-on-rails ruby-on-rails-4

我有一个N + 1问题,我无法解决。我在此处托管了一个展示问题的示例应用:https://github.com/davidmles/question_parts

这是它的工作原理:

有4个模型:question,question_part,answer和answer_part。 一个问题有N个部分,也有N个答案。答案有N个部分。答案部分属于答案和问题部分(一个人正在回答)。

答案可以是草稿或已发布。草稿不需要回答所有部分,而已公布的答案确实需要回答。

问题:

创建答案但未回答所有部分,并尝试发布时,验证将失败,编辑表单将再次显示。在验证失败后显示编辑表单时,会出现N + 1问题,因为答案部分会加载相应的问题部分,而不会急于加载它们。

我试图加载它们,但编辑表单不会显示正确的错误。

我怎么能解决这个问题?我在应用自述文件中添加了更多信息,以及指导您查看问题的步骤:https://github.com/davidmles/question_parts/blob/master/README.md

2 个答案:

答案 0 :(得分:3)

坏消息:似乎ActiveRecord在集合关联中与#includes不能很好地匹配。实际上你不能破解它,因为它不会持久存在关系对象(here)。

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

has_many :question_parts, through: :parts添加到您的答案模型中。之后在answers_controller中使用此finder:@answer = Answer.preload(:question_parts).where(id: params[:id]).first。有时子弹宝石不喜欢它(它表示未使用的急切加载blabla但它不是真的)但没有N + 1查询,表单工作正常。

答案 1 :(得分:1)

为了补充Flash Gordon的答案,查询也可以这样写:

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

因此,不需要修改Answer

此外,使用includes代替preload似乎有效(Rails在这种情况下选择正确的策略)。