Eager Loading Multiple Associations and serialization

729 views Asked by At

In my project I have 3 models Assignment, Question and MultipleChoice with the following associations

assignment.rb

has_many :questions,  dependent: :destroy

question.rb

belongs_to :assignment, class_name: 'Assignment', foreign_key: :assignment_id
  has_many :multiple_choices, dependent: :destroy

multiple_choice.rb

belongs_to :question

Now I want to make a query like below

@assignment = Assignment.find(params[:id])
        @questions = @assignment.questions.includes(:multiple_choices)
This is not working as expected.

So, I want all questions that belongs to the assignment for the params[:id] and the associated multiple choices that belongs to a question. My above query do not give any error but it only show questions not multiple choices associated with question. How can I do this? I am learning api development for rails. So I want to send this value as json and probably I will need serialization. How can I do this? I am working on rails 4.

Edit

well the output for

@questions = @assignment.questions.includes(:multiple_choices) and 
@questions = @assignment.questions.eager_load(:multiple_choices) and
@questions = @assignment.questions  are all same.

I dont understand why the output do not include any value from multiple choices table

Output of the command

@assignment.questions.eager_load(:multiple_choices).to_sql id
    => "SELECT \"questions\".\"id\" AS t0_r0, \"questions\".\"content\" AS t0_r1, \"questions\".\"q_type\" AS t0_r2, \"quest
    ions\".\"created_at\" AS t0_r3, \"questions\".\"updated_at\" AS t0_r4, \"questions\".\"assignment_id\" AS t0_r5, \"multi
    ple_choices\".\"id\" AS t1_r0, \"multiple_choices\".\"content\" AS t1_r1, \"multiple_choices\".\"created_at\" AS t1_r2,
    \"multiple_choices\".\"updated_at\" AS t1_r3, \"multiple_choices\".\"question_id\" AS t1_r4 FROM \"questions\" LEFT OUTE
    R JOIN \"multiple_choices\" ON \"multiple_choices\".\"question_id\" = \"questions\".\"id\" WHERE \"questions\".\"assignm
    ent_id\" = $1"
2

There are 2 answers

0
Chitra On

@assignment is an object from which you are getting the questions.

But with @questions = @assignment.questions.includes(:multiple_choices) how can you get the multiple_choices without calling this on an object?

Try this->

@assignment = Assignment.includes(:questions).find(params[:id]) @assignment.questions.includes(:multiple_choices).collect {|question| question.multiple_choices }

This also includes eager loading.

Hope you'll get what you expect.

1
Yury Lebedev On

The behaviour for includes function changed in Rails 4. You can find more details here:

http://blog.arkency.com/2013/12/rails4-preloading/

I also suppose, that if you will use eager_load instead of includes, you will get the result you need.