我有一个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
答案 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在这种情况下选择正确的策略)。