2016-08-16 1 views
0
class Comment < ActiveRecord::Base 
    has_many :replies 
end 

class Reply < ActiveRecord::Base 
    belongs_to :comment 
end 

Мне нужно получить комментарии, только что от кого ответы.Как мне получить только некоторые из атрибутов отношения has_many?

У меня есть это в моем замечании модели:

scope :with_replies_by_users, ->(*user_ids) { 
joins(:replies).where(replies: { user_id: user_ids }) 
} 


@comments = Comment.with_replies_by_users([1,2]) 

Я думаю, что это будет возвращать все комментарии, которые имеют ответы на 1 или 2. Но она возвращает все из ответов на эти замечания. Мне нужны только те ответы от 1 или 2.

+0

Я считаю, что оператор splat * звездочка * создает многоразмерный массив. Попробуйте удалить его из области 'with_replies_by_users' –

+0

@GregAnswer - я пробовал это в обоих направлениях, и я получаю те же результаты. – atarihomestar

ответ

0

Причина, по которой вы все еще получаете ответы от всех пользователей с вашим примером области видимости, заключается в том, что эти условия используются для запроса комментариев. Другими словами, он служит только для определения того, какие комментарии извлекаются из базы данных.

Например, вот 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 
Смежные вопросы