【问题标题】:How to refactor this Model logic in Rails如何在 Rails 中重构此模型逻辑
【发布时间】:2014-12-30 22:09:58
【问题描述】:

我有教师模型,它有很多学生。然后学生有很多科目。 基于这种关系,我需要准备一份报告..

这里我只是通过包含语句组合每个实体,然后循环以获取所需格式的数据(哈希数组)。

#teacher.rb

      def get_students_report
        teachers = Teacher.includes(students: :subjects)

        final_result = []
        teachers.each do |teacher|
          students = teacher.students
          teacher_name = teacher.full_name
          classes_taken = teacher.classes_count 

          students.each do |student|
            student_name = student.name
            attendance = (student.days_attended/classes_taken.to_f) * 100.0
            subjects = student.subjects
            final_result = 0
            subject_total = subjects.sum(:marks_obtained)
            #show in percentage
            mark_in_percentage = (subject_total * 100)/subjects.sum(:maximum_mark).to_f 

            students_record = {
              student_name: student_name
              teacher_name: teacher_name
              attendance: attendance, 
              subject_total: subject_total
              subject_percentage: mark_in_percentage
            }
            final_result.push student_record

         end #end of student loop
        end #end of teacher loop
      end  #end of method.

上述解决方案工作正常。但我觉得这有以下缺陷: - 这种方法太大了,将来如果我需要更多的列,那么它会增长更多。 - 代码不能很好地维护。

我们能有更好的方法吗?

【问题讨论】:

  • 对于初学者来说,这看起来应该是一个类方法。
  • 其次,有很多不必要的赋值语句。存储 student_name 与仅调用 student.name 之间应该没有太大的性能差异。
  • 我会在Student 上创建一个方法,即def record_for_teacher(teacher),并将大部分学生块逻辑移至Student 模型。
  • 使用record_for_teacher,我们会从学生模型中得到student_name、出席率、marks_in_percentage、subject_total,所以可以减少大约4/5行的代码?学生模式是一个更好的继续前进的地方吗?因为这些计算没有执行那么严重的数据库操作?可以使用装饰者/关注者的任何帮助吗?
  • 老师和学生是什么关系?老师has_many学生,但是学生belong_to老师呢?

标签: ruby-on-rails model refactoring rails-activerecord


【解决方案1】:

假设一个老师has_many学生和一个学生belongs_to一个老师,你可以如下:

Teacher.rb

has_many :students, inverse_of: :teacher

def self.get_students_report
  self.includes(student: :subjects).map(&:students_reports).flatten
end

def students_reports
  students.map(&:record).flatten
end

Student.rb

belongs_to :teacher, inverse_of: :students

def record
  {
    student_name: name,
    teacher_name: teacher.name,
    attendance: attendance, 
    subject_total: subject_total,
    subject_percentage: mark_in_percentage
  }
end

private

def attendance
  (student.days_attended/classes_taken.to_f) * 100.0
end

def classes_taken
  teacher.classes_count
end

def subject_total
  subjects.sum(:marks_obtained)
end

def mark_in_percentage
  (subject_total * 100)/subjects.sum(:maximum_mark).to_f
end

【讨论】:

  • 你是我的男人!你听起来绝对有道理。我一定会尝试这种方法并尽早回到这里!再次感谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多