активная запись, возвращающая все отношения объекта, которые заархивированы: ложь

#ruby-on-rails #ruby #activerecord

Вопрос:

В ruby on rails у меня есть модель пользователей, у этого пользователя может быть потенциальное соответствие либо в качестве наставника, либо в качестве подопечного. Эти потенциальные совпадения могут быть либо заархивированы: истинно, либо заархивировано ложно, и я не могу заставить этот запрос работать хоть убей.

 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

 

что я здесь упускаю? это сводит меня с ума.

Комментарии:

1. проверьте значения в таблице базы данных, особенно «potential_matches», чтобы проверить, присутствуют ли архивные значения или нет.

2. Этот код не имеет ни малейшего смысла. Я предполагаю, что область действия — это модель пользователя, поэтому она вернет коллекцию записей пользователей, а не потенциальных совпадений. И я не могу понять, что ты пытаешься сделать такого, чего нельзя было бы просто достичь PotentialMatch.where(archived: false) . Почему этот код даже в пользовательской модели?

3. Это имело бы смысл только в том случае, если это метод экземпляра, а вы получаете потенциальные совпадения для конкретного пользователя. Возможно, вы захотите начать все сначала и объяснить нам, чего вы на самом деле пытаетесь достичь.

4. да. Я понял, что запрос не возвращает потенциальных совпадений, лол. Я устал после 15 часов работы. хотя спасибо за ответ.

Ответ №1:

Если вы пытаетесь получить пользователей без каких-либо архивных совпадений, самый простой способ-создать подзапрос:

 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  ?