Coda Chang Coda Chang - 2 months ago 11
Ruby Question

Rails N+1 query with has_many association

The model relationship is

section has_many :sections
section belong_to :section
section has_many :questions
question_set has_many :questions, :through => :question_sets_questions


I encounter N+1 query problem, but I don't know how to figure it out.

Here is code

def test
question_set_id = params[:qset_id].to_i
q_ids = QuestionSetsQuestion.where(:question_set_id => question_set_id).pluck(:question_id)
questions = Question.where(:id => q_ids).includes(:section)
questions.each do |q|
section = {id: q.section.id, name: q.section.name}
parent_section = q.section.section rescue nil
p parent_section.id
end
end


The
bullet
gem said

N+1 Query detected
Section => [:section]
Add to your finder: :include => [:section]
N+1 Query method call stack


Do I put the includes wrongly?

Update



Thanks @Deepak,
.includes(section: :section)
can solve two layers of sections. But actually I got three hierarchies of sections. The original code looks like

questions.each do |q|
section = {id: q.section.id, name: q.section.name}
parent_section = q.section.section rescue nil
while parent_section.present?
section = {id: parent_section.id, name: parent_section.name, children: [section]}
parent_section = parent_section.section rescue nil
end
p section
end

Answer

first thing the associations are really confusing.

I think you are calling two hierarchies of sections on question, so changing this line should work

questions = Question.where(:id => q_ids).includes(section: :section)

You are accessing the parent section of q.section so we need to include that as well

parent_section = q.section.section rescue nil

EDIT

Its getting messier I am not sure if you should do this but i think this will solve the problem

questions = Question.where(:id => q_ids).includes(section: [section: :section])
Comments