返回归档对象的所有关系的活动记录:false

active record returning all relations of an object that are archived: false

在 rails 上的 ruby 中,我有一个用户模型,此用户可以有一个 potential_match 作为导师或受训者。这些 potential_matches 可以存档:true,或存档 false,我无法让这个查询为我的生活工作。

scope :potential_matches,
        -> {
          joins('LEFT JOIN potential_matches ON potential_matches.mentor_id = users.id OR potential_matches.mentee_id = users.id')
          .where('potential_matches.archived = false')
          .where('users.active = true')
        }

总是失败的测试如下:

describe '.potential_matches' do
    it 'returns only active potential matches' do
      user1 = FactoryBot.create(:user)
      user2 = FactoryBot.create(:user)
      user3 = FactoryBot.create(:user)
      user4 = FactoryBot.create(:user)
  
      pot_match1 = FactoryBot.create(:potential_match, {mentor_id: user1.id, mentee_id: user2.id})
      pot_match2 = FactoryBot.create(:potential_match, {mentor_id: user2.id, mentee_id: user1.id})
      pot_match3 = FactoryBot.create(:potential_match, {mentor_id: user3.id, mentee_id: user4.id, archived: true})
      pot_matches = User.potential_matches
      expect(pot_matches).to include(pot_match1, pot_match2)
      expect(pot_matches).not_to include(pot_match3)
    end
  end

我在这里错过了什么?这让我发疯。

如果您要做的是在没有任何存档匹配项的情况下获取用户,最简单的方法是创建子查询:

class User < ApplicationRecord
  def self.potential_matches
    pm = PotentialMatch.arel_table
    id = arel_table[:id]
    where(
      PotentialMatch.where(
        pm[:mentor_id].eq(id).or(pm[:mentee_id].eq(id))
      ).where(archived: true).arel.exists.not
    ).where(active: true)
  end
end

这会生成以下内容 SQL:

SELECT "users".*
FROM   "users"
WHERE  NOT ( EXISTS (SELECT "potential_matches".*
                     FROM   "potential_matches"
                     WHERE  ( "potential_matches"."mentor_id" = "users"."id"
                               OR "potential_matches"."mentor_id" =
                            "users"."id" )
                            AND "potential_matches"."archived" = ?) )
       AND "users"."active" = ? /* loading for inspect */
LIMIT  ?