我最近得到了热切的加载以及提高性能的必要性。我设法从加载此页面中删除了一些查询,但我怀疑如果我能够正确地加载所需的记录,我可以将它们显着减少。
此控制器需要加载以下所有内容才能填充视图:
学生
学生正在查看的研讨会(班级)页面
该研讨会中包含的所有目标
objective_seminars,目标和研讨会之间的联接表。这包括列"优先级"这是由老师设定的,用于订购目标。
objective_students,另一个连接表。包括一个列"点"学生在该目标上的得分。
semin_students,最后一个联接表。包括学生可以调整的一些设置。
控制器:
def student_view
@student = Student.includes(:objective_students).find(params[:student])
@seminar = Seminar.includes(:objective_seminars).find(params[:id])
@oss = @seminar.objective_seminars.includes(:objective).order(:priority)
@objectives = @seminar.objectives.order(:name)
objective_ids = @objectives.map(&:id)
@student_scores = @student.objective_students.where(:objective_id => objective_ids)
@ss = @student.seminar_students.find_by(:seminar => @seminar)
@teacher = @seminar.user
@teach_options = teach_options(@student, @seminar, 5)
@learn_options = learn_options(@student, @seminar, 5)
end
下面的方法是发生了许多重复查询,我认为应该通过急切加载来消除这些查询。这种方法为学生提供了六种选择,因此她可以选择一个目标来教她的同学。该方法首先考虑的是学生得分在75%到99%之间的目标。在该括号内,它们也按" priority"排序。 (来自objective_seminars连接表。此值由教师设置。)如果有更多空间,则该方法查看学生得分100%的目标,按优先级排序。 (learn_options方法实际上与此方法相同,但具有不同的括号。)
teach_options方法:
def teach_options(student, seminar, list_limit)
teach_opt_array = []
[[70,99],[100,100]].each do |n|
@oss.each do |os|
obj = os.objective
this_score = @student_scores.find_by(:objective => obj)
if this_score
this_points = this_score.points
teach_opt_array.push(obj) if (this_points >= n[0] && this_points <= n[1])
end
end
break if teach_opt_array.length > list_limit
end
return teach_opt_array
end
提前感谢您的任何见解!
答案 0 :(得分:0)
@jeff - 关于你的问题,我没有看到@student_scores.find_by(:objective => obj)
之外会发生很多疑问。
您的@student_scores
对象已经是ActiveRecord关系,对吗?因此,您可以对此使用.where()
,或.select{}
,而无需再次访问数据库。选择会留下一个数组,而不是AR关系,所以要小心。
this_score = @student_scores.where(objectve: obj)
this_score = @student_scores.select{|score| score.objective == obj}
那些应该有效。
关于您的顶级控制器方法的其他一些建议 - 我没有看到任何警卫或防御性编码,因此如果这些对象中的任何一个为零,则您的.order(:blah)
可能会出错。此外,如果它们返回nil,则依赖于其数据的后续查询可能会出错。我会选择一些try()
或救援。
最后,只是挑剔,但前两行有点难以阅读,因为你可能错误地将params解释为应用于包含以及主要对象:
@student = Student.includes(:objective_students).find(params[:student])
@seminar = Seminar.includes(:objective_seminars).find(params[:id])
我将查找与您的主要对象,然后是包括:
@student = Student.find(params[:student]).includes(:objective_students)
@seminar = Seminar.find(params[:id]).includes(:objective_seminars)