views:

10

answers:

0

How do I eager-load only some of the objects in a has_many relationship?

Basically, I have four objects: Assignment, Problem, AssignmentUser, and ProblemUser.

#assignment.rb
has_many :problems
has_many :assignment_users

#assignment_user.rb
belongs_to :assignment
belongs_to :user
has_many :problem_users

#problem.rb
belongs_to :assignment
has_many :problem_users

#problem_user.rb
belongs_to :user
belongs_to :problem
belongs_to :assignment_user
attr_accessor :complete #boolean

On a page showing a single assignment, I want to show all of the problems, as well the user's status on each problem, if it exists. (It might not, if this is the first time the user is viewing the page.)

I can't call assignment_user.problem_users and then snake the problems out like so:

-@assignment_user.problem_users.each do |problem_user|
    = check_box_tag "problems[#{problem_user.problem.id}]", 1, problem_user.complete
    = link_to problem_user.problem.name, assignment_problem_path(assignment_id => problem_user.problem.assignment_id, :id => problem_user.problem_id)

because there might not be ProblemUser entries for every Problem that belongs to an assignment; creating all of those ProblemUser objects whenever someone creates a Problem object would be wasteful, so they're only created on the fly.

What I want is to be able to iterate over the Problems that belong to the particular Assignment, then for each Problem, find a ProblemUser that matches...but without creating an N+1 problem. I could create two arrays, one with all of the problems and one with all of the problem_users, but then I would have to match them up, right? Maybe that's the best way... but any recommendations on best practices are appreciated here.