Coda Chang Coda Chang - 1 year ago 119
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:, name:}
parent_section = q.section.section rescue nil

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?


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:, name:}
parent_section = q.section.section rescue nil
while parent_section.present?
section = {id:, name:, children: [section]}
parent_section = parent_section.section rescue nil
p section

Answer Source

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


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])
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download