根据条件急切加载所有has_many对象的一小部分

时间:2010-08-13 21:12:31

标签: ruby-on-rails activerecord

如何只加载has_many关系中的某些对象?

基本上,我有四个对象:AssignmentProblemAssignmentUserProblemUser

#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

在显示单个作业的页面上,我想显示所有问题,以及用户在每个问题上的状态(如果存在)。 (如果这是用户第一次查看该页面,则可能不会。)

我不能打电话给assignment_user.problem_users,然后把问题解决掉:

-@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)

因为属于某个作业的每个ProblemUser可能没有Problem个条目;每当有人创建ProblemUser对象时创建所有这些Problem对象将是浪费,因此它们只是在运行中创建。

我想要的是能够迭代属于特定Problems的{​​{1}},然后对于每个Assignment,找到匹配的Problem。 。但没有造成N + 1问题。我可以创建两个数组,一个包含所有问题,一个包含所有的problem_users,但是我必须匹配它们,对吧?也许这是最好的方式......但是这里有关于最佳实践的建议。

1 个答案:

答案 0 :(得分:0)

尝试使用:include 的内容......

#assignment.rb
has_many :problems, :include => :problem_user
has_many :assignment_users

假设在每个表赋值,问题和problem_users中都有一个名为description的字段,那么解决方案应该与此类似......

Assignment.find(1).problems.collect { |a| [a.assignment.description, a.description, a.problem_user.description] }