#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 ?