Rails避免在具有连接和合并的范围上重复连接

时间:2017-03-01 18:25:43

标签: ruby-on-rails

我试图重构一个有很多has_many的模型:通过涉及连接表条件的关联

class Assignment
  has_many :assignment_reviewers
  has_many :preferred_assignment_reviewers, -> { preferred }
  # more of these for different types of reviewers

  has_many :reviewers, through: :assignment_reviewers
  has_many :preferred_reviewers, through: :preferred_assignment_reviewers
  # more of these

我在Reviewer上添加了以下范围

class Reviewer
  scope :preferred, -> do
    joins(:assignment_reviewers).merge(AssignmentReviewer.preferred)

这样我才能做到

assignment.reviewers.preferred

而不是使用has_many

assignment.preferred_reviewers

然而,前者导致重复的INNER JOIN

INNER JOIN `assignment_reviewers` `assignment_reviewers_reviewers`
ON `assignment_reviewers_reviewers`.`reviewer_id` = `reviewers`.`id`
INNER JOIN `assignment_reviewers`
ON `reviewers`.`id` = `assignment_reviewers`.`reviewer_id`

似乎我有三个选择:

  1. 继续为每个定义has_manys和has_many:throughs(缺点:已经是神级的模型上的许多特定关联)
  2. 使用范围(缺点:重复连接)
  3. 直接使用合并

    assignment.reviewers.merge(AssignmentReviewer.preferred)
    

    (缺点:不那么雄辩)

  4. 我倾向于选择选项2,因为更清晰的代码和我猜测额外加入不会对性能产生重大影响。

    任何建议/我有没有更好的选择?

1 个答案:

答案 0 :(得分:0)

我找到了一个比我列出的三个更好的解决方案:

我在我的has_many中添加了一个扩展块:通过声明

has_many :reviewers, through: :assignment_reviewers do
  def preferred
    merge(AssignmentReviewer.preferred)
  end
end

虽然我仍然需要声明很多扩展,但这比通过我需要的每个has_many声明has_many和has_many更简洁