Rails:基于非数据库字段对 ActiveRecord 关系进行排序,同时保持 ActiveRecord 关系

问题描述 投票:0回答:1

我正在开发一个 Rails 应用程序,我需要根据关联的 TutorSubject 记录的最低分数对 Tutor 记录进行排序。我面临的挑战是 TutorSubject 模型中的 Strength_score 方法表示的分数不是数据库字段,而是返回表示数字的字符串的 Ruby 方法。

这是我的模型的基本结构:

  1. 每个导师都有许多导师主题。
  2. 每个 TutorSubject 都有一个 Strength_score 方法,以字符串形式返回分数。

我的目标是根据所有相关 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 查询中,或者有其他方法可以实现高效分页?

任何见解或替代方法将不胜感激!

ruby-on-rails ruby sorting activerecord
1个回答
0
投票

根据您当前的方法,您可以执行以下操作:

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)')
© www.soinside.com 2019 - 2024. All rights reserved.