我正在开发一个 Rails 应用程序,我需要根据关联的 TutorSubject 记录的最低分数对 Tutor 记录进行排序。我面临的挑战是 TutorSubject 模型中的 Strength_score 方法表示的分数不是数据库字段,而是返回表示数字的字符串的 Ruby 方法。
这是我的模型的基本结构:
我的目标是根据所有相关 TutorSubjects 中的最低强度分数对导师进行排序。我可以计算每个导师的最低分数并在 Ruby 中对导师进行排序,但这会将我的 ActiveRecord 关系转换为数组,从而阻止我使用 ActiveRecord 的分页方法。
这是我尝试过的片段:
tutor_subjects = TutorSubject.includes(:tutor, :evaluations)
.where(id: Evaluations::Evaluation.where(evaluatable_type: "TutorSubject").select(:evaluatable_id))
min_scores_per_tutor = {}
tutor_subjects.each do |tutor_subject|
tutor_id = tutor_subject.tutor_id
score_str = tutor_subject.strength_score
next unless score_str.match?(/\A\d+\z/)
score = score_str.to_i
min_scores_per_tutor[tutor_id] = score if min_scores_per_tutor[tutor_id].nil? || score < min_scores_per_tutor[tutor_id]
end
tutors = Tutor.where(id: min_scores_per_tutor.keys)
# After this point, 'tutors' is still an ActiveRecord relation
当我尝试对此进行排序时,问题出现了:
sorted_tutors = tutors.sort_by { |tutor| min_scores_per_tutor[tutor.id] }
# 'sorted_tutors' is now an Array, not an ActiveRecord relation
我需要将排序结果保留为 ActiveRecord 关系,以便我可以使用内置的 ActiveRecord 分页方法对其进行分页。如何执行此排序,同时将结果保持为 ActiveRecord 关系?有没有办法将这种基于 Ruby 方法的排序逻辑合并到 ActiveRecord 查询中,或者有其他方法可以实现高效分页?
任何见解或替代方法将不胜感激!
根据您当前的方法,您可以执行以下操作:
sorted_tutors = Tutor
.where(id: min_scores_per_tutor.keys)
.order(Arel.sql("CASE tutors.id #{min_scores_per_tutor.map {|tutor_id, score| "WHEN #{tutor_id} THEN #{score}" }.join(' ')} END ASC"))
更好的方法是将
strength_score
存储为整数而不是字符串,然后通过关联表上 SQL 中的 min
聚合函数进行排序,例如:
Tutor.joins(:tutor_subjects).group(:id).order('min(tutor_subjects.strength_score)')