2014-02-26 3 views
0

У меня есть ряд моделейУплотненного ActiveRecord отношения в Rails

class User < ActiveRecord::Base 
    belongs_to :group 
end 

class Group < ActiveRecord::Base 
    has_many :users 
    has_many :posts 
end 

class Post < ActiveRecord::Base 
    belongs_to :group 
    has_many :comments 
end 

class Comment < ActiveRecord::Base 
    belongs_to :post 
end 

Чтобы получить пост пользователя, я могу сделать User.find(1).group.posts.all, но если я хочу все комментарии для сообщений пользователя Я не могу сделать User.find(1).group.posts.all.comments.all.

Есть ли простые решения, чтобы получить все комментарии к сообщениям пользователя, кроме прокрутки всех сообщений?

+0

Основываясь на комментарии Sævar о моем ответе ниже, я думаю, было бы неплохо указать, что User.find (1) .group.p osts извлекает все сообщения в группе пользователя, а не только те, что сделаны этим пользователем. Это то, что вы хотите? – Coenwulf

ответ

1

Единое решение запроса:

Comment.joins(post: {group: :users}).where(users: {id: 1}) 

Результирующий запрос:

SELECT "comments".* FROM "comments" 
    INNER JOIN "posts" ON "posts"."id" = "comments"."post_id" 
    INNER JOIN "groups" ON "groups"."id" = "posts"."group_id" 
    INNER JOIN "users" ON "users"."group_id" = "groups"."id" 
    WHERE "users"."id" = 1 
2

То, что вы хотите это has_many через отношения: http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

Добавьте следующие строки в группе класса

has_many :comments, through: :posts 

Тогда вы можете получить комментарии с:

User.find(1).group.comments 
+0

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

+0

Хорошая точка, но на основе того, как OP получил сообщения (User.find (1) .group.posts) Я предполагаю, что это желаемое поведение. Если не нужно изменить структуру базы данных. – Coenwulf

+0

Ну, ОП говорит: «Получите все комментарии к сообщениям пользователя», так что я и предполагал. Структура базы данных прекрасна, трюк состоит в том, чтобы придумать эффективный запрос. –

-1

Просто добавив has_many :comments, through: :posts недостаточно. Затем запрос вроде User.find(1).group.comments предоставит вам все комментарии для группы пользователей, а не указанного пользователя.

Другой способ посмотреть все почтовые идентификаторы для данного пользователя и использовать, чтобы найти комментарии для сообщений этого пользователя:

post_ids = User.find(1).group.posts.map(&:id).uniq 
user_comments = Comment.where(:post => post_ids) 
+0

Это вызовет запрос для каждого сообщения, что очень неэффективно. Это называется запросом N + 1, см. Http://stackoverflow.com/questions/97197/what-is-the-n1-selects-issue –

+1

Нет, это фактически приводит к запросам в 3 sql. Один для выбора пользователя. Затем, например, чтобы выбрать сообщения на основе группы пользователей: выберите сообщения. * Из сообщений, где posts.group_id = 1. Третий выбирает комментарии, используя запрос типа: SELECT comments. * Из комментариев, где comments.post_id IN [ 1,2,3,4,5] –

+0

Вы правы, извините. Однако это будет по-прежнему плохо работать, потому что вам нужно прочитать значения из базы данных в Ruby, просто чтобы вернуть их обратно для выбора комментариев, а не для JOIN. –

Смежные вопросы