Причина, по которой вы все еще получаете ответы от всех пользователей с вашим примером области видимости, заключается в том, что эти условия используются для запроса комментариев. Другими словами, он служит только для определения того, какие комментарии извлекаются из базы данных.
Например, вот SQL, который запускается с областью:
>> comments = Comment.joins(:replies).where(replies: { user_id: [2, 3] })
Comment Load (0.3ms) SELECT "comments".* FROM "comments" INNER JOIN "replies" ON "replies"."comment_id" = "comments"."id" WHERE "replies"."user_id" IN (2, 3)
Это просто сказать «выберите комментарии, основанные на результатах внутреннего соединения с таблицей ответов.» В результате ответов довольно много бессмысленно прямо сейчас, потому что, как только вы получаете доступ приписывать ответы на любой из комментариев:
>> comments.first.replies
Reply Load (0.2ms) SELECT "replies".* FROM "replies" WHERE "replies"."comment_id" = ? [["comment_id", 1]]
ActiveRecord будет делать отдельный поиск в таблице ответов, потому что не считает область обзора комментариев.
Решение
Для меня это выглядит, как вы больше озабочены ответов, чем комментарии. Поэтому один из способов я бы подойти к этому запросу является путем запроса таблицы ответов вместо этого, но с жадной загрузкой:
>> replies = Reply.includes(:comment).where(user_id: [2, 3])
Reply Load (0.4ms) SELECT "replies".* FROM "replies" WHERE "replies"."user_id" IN (2, 3)
Comment Load (0.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."id" = 1
Наконец, у вас есть ответы только для конкретных идентификаторов пользователей. У вас уже есть комментарии так же из-за высокой загрузки. Например, выполнение следующих действий не приведет к дополнительным выборкам, поскольку эти комментарии хранятся в памяти.
>> replies.map(&:comment)
Но будьте осторожны, чтобы не получить доступ к атрибуту ответов на одном из комментариев моделей снова, либо ActiveRecord будет делать другой выборки:
>> replies.map(&:comment).first.replies
Reply Load (0.2ms) SELECT "replies".* FROM "replies" WHERE "replies"."comment_id" = ? [["comment_id", 1]]
Если вы хотите, чтобы все-таки сделать это сфера , он бы сейчас пойти в модели Ответ:
scope :from_users, -> (*user_ids) do
includes(:comment).where(user_id: user_ids)
end
Тогда звоните:
>> Reply.from_users [2, 3]
Reply Load (0.1ms) SELECT "replies".* FROM "replies" WHERE "replies"."user_id" IN (2, 3)
Comment Load (0.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."id" = 1
Я считаю, что оператор splat * звездочка * создает многоразмерный массив. Попробуйте удалить его из области 'with_replies_by_users' –
@GregAnswer - я пробовал это в обоих направлениях, и я получаю те же результаты. – atarihomestar