2017-08-07 87 views
0

我最近已经倾注了急切的加载和提高性能的必要性。我已经设法减少加载这个页面的一些查询,但是我怀疑如果我能够正确地加载所需的记录,我可以将它们减少很多。我需要一些帮助实现急切的加载

该控制器需要加载以下所有的来填充视图:

  • 一个学生

  • 研讨会(类)页面,学生正在查看

  • 所有包含在该研讨会中的目标

  • objective_seminars,目标之间的连接表和研讨会。其中包括由教师设定的用于订购目标的“优先级”栏。

  • 这个objective_students是另一个连接表。包括学生在该目标上得分的专栏“分数”。

  • seminar_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%之间的目标。在该括号内,它们也按照“优先级”排序(来自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

@jeff - 关于您的问题,我看不到@student_scores.find_by(:objective => obj)之外会发生大量查询。 您的@student_scores对象已经是ActiveRecord关系,对不对?所以你可以在这个上使用.where(),或者.select{}而不用再次敲击db。选择会让你留下一个阵列,而不是一个AR关系,所以要小心。

this_score = @student_scores.where(objectve: obj) 
this_score = @student_scores.select{|score| score.objective == obj} 

那些应该工作。

只是在您的顶级控制器方法的一些其他建议 - 我没有看到任何守卫或防守编码,所以如果这些对象中的任何一个是零,您的.order(:blah)可能会出错。此外,如果他们返回零,您后续的查询依赖于他们的数据可能会出错。我会选择一些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) 
+0

你是说“其中”不发送另一个命中分贝,但“find_by”呢?如果是这样,这是有道理的。此外,链末尾的“includes”语法是我首先尝试的方式。它这样引发了一个错误。 –