has_many: сквозной, когда объединяющая таблица не содержит FK для обеих таблиц - PullRequest
1 голос
/ 14 января 2011

У меня есть структура, которая на самом деле не является примером has_many :through, но я бы хотел, чтобы она велась так:

# user.rb
belongs_to :blog
has_many :posts

# post.rb
belongs_to :user

# blog.rb
has_many :users
has_many :posts, :through => :users  # this obviously doesn't work becase
                                     # both FKs aren't in the blogs table

Я хочу получить ВСЕ посты для блога в массиве,Я знаю, что я могу сделать это с Ruby, используя each или получая фантазию с collect, но я бы хотел, чтобы SQL выполнял эту работу.

Может кто-нибудь объяснить, как я могу настроить свои модели таким образом, чтобы я мог называть @ blog.posts с использованием SQL и Ruby, и объяснить, какой путь «лучше»?

Edit:

Я знаю, что в SQL я могу написать что-то вроде:

SELECT * FROM posts WHERE posts.user_id IN (
  SELECT users.id FROM users WHERE users.blog_id = 7
)

, что, очевидно, показывает, что необходимы два запроса.Я не думаю это возможно с join, но я не совсем уверен.Очевидно, что подзапрос необходим, но как мне получить рельсы для создания этого подзапроса с ARel вместо того, чтобы возвращать и использовать Ruby для зацикливания и сбора и тому подобное?

1 Ответ

2 голосов
/ 14 января 2011

Попробуйте добавить это в вашу Post модель

scope :for_blog, lambda{|blog|
  where("user_id IN (SELECT u.id FROM users u WHERE u.blog_id = ?)", blog.id)
}

Это позволит вам позвонить Post.for_blog(@blog). Объекты, возвращаемые SQL, должны быть преобразованы как Post s (поэтому я бы поместил область действия в модель Post).

Затем в вашей Blog модели поместите

def posts
  Post.for_blog(self)
end

Определив виртуальный атрибут, вы теперь сможете получить доступ к сообщениям блога через @blog.posts.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...