使用条件预加载嵌套资源

时间:2017-02-20 22:26:55

标签: mysql ruby-on-rails ruby

在我的简单出勤应用中,有:students:semesters:attendances。出席时有student:references semester:references date:date present:boolean列。

semester.rb

class Semester < ApplicationRecord
  has_and_belongs_to_many :students
  accepts_nested_attributes_for :students
end

student.rb

class Student < ApplicationRecord
  has_and_belongs_to_many :semesters
  has_many :attendances, dependent: :destroy
  accepts_nested_attributes_for :attendances
end

attendance.rb

class Attendance < ApplicationRecord
  belongs_to :semester
  belongs_to :student
  validates_presence_of :date
end

semesters#show页面中,我想显示该学期的每位学生,以及每位学生的出勤率,如下所示。

attendance

它有效,但在开始计算之前,我必须过滤掉与学期无关的一些:attendances。因此,我的目标是急切加载学期,学生以及仅属于那个学期的出勤率。

这样,当我使用

@semester.students.each do |student|
  student.attendances
end

.attendances方法只应返回与该学期相关的方法。这可能吗?

这是我得到的

# semesters_controller.rb
def show
  @semester = Semester.includes(students: [:attendances])
                      .order('students.first_name')
                      .find params[:id]
end

# students_helper.rb
def student_attendance(student)
  total = student.attendances.select { |x| x.semester_id == @semester.id }
  present = total.select &:present
  percent = (present.size/total.size.to_f * 100).round rescue 0
  link_to student, class: 'attendance', style: "width: #{percent}%" do
    <<-HTML.html_safe
      <span>#{student.first_name}</span>
      <span>#{percent}%</span>
    HTML
  end
end

我发现使用select {|x| x.semester_id == @semester.id }代替where semester_id: @semester.idselect &:present代替where present: true会减少查询次数。

无论如何,有没有办法可以加载:attendances以便我不必通过第一个过滤器(select {|x| x.semester_id == @semester.id })?如果我不像我正在做的那样过滤,那么它将显示学生的所有学期的出勤率,而不仅仅是这一学期我们正在努力在#show页面上显示。

我只是不想加载所有不必要的数据,是吗?感谢。

1 个答案:

答案 0 :(得分:1)

看起来您已经有办法直接将出勤与学期联系起来了(因为belongs_to :semester已在您的出勤课程中说明。

你试过了吗?

class Semester < ApplicationRecord
  has_and_belongs_to_many :students
  has_many :attendences
end
attendences = @semester.attendences

或者只是:

attendences = Attendence.where(semester: params[:id])

(您可以使用适当的连接/包括来减少sql查询)