2009-05-04 5 views
1

Я строй небольшого щебетать стиль сервиса микроблоггинга, где пользователи могут следовать другим пользователям и получить фид своих сообщенийнесколько объединений с использованием ActiveRecord в рельсах

У меня есть следующие модели:

class Follow < ActiveRecord::Base 
    belongs_to :follower, :class_name => "User" 
    belongs_to :followee, :class_name => "User" 
end 

class User < ActiveRecord::Base 
    has_many :follows, :foreign_key => 'follower_id', 
         :class_name => 'Follow' 
    has_many :followers, :through => :follows 
    has_many :followed, :foreign_key => 'followee_id', 
         :class_name => 'Follow' 
    has_many :followees, :through => :followed 
    has_many :messages 
end 

class Message < ActiveRecord::Base 
    belongs_to :user 
end 

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

SELECT * FROM follows JOIN users JOIN messages WHERE follows.follower_id = current_user.id AND follows.followee_id = users.id AND users.id = messages.user_id; 

Что такое правильный способ ActiveRecord это сделать?

ответ

1

Не уверен, что вы ищете, но вот мое предложение:

Я предполагаю, что у вас есть другие цели для этого последующего класса, в противном случае я не вижу цель этого.

«Правильный путь» (т.е. мой полностью субъективный путь), чтобы сделать это было на самом деле что-то вроде этого:

class User < ActiveRecord::Base 
    has_and_belongs_to_many :followers, :foreign_key => 'followed_id', 
     :class_name => 'User', :association_foreign_key => 'follower_id', 
     :include => [:messages] 
    has_and_belongs_to_many :follows, :foreign_key => 'follower_id', 
     :class_name => 'User', :association_foreign_key => 'followed_id' 
    has_many :messages 
end 

class Message < ActiveRecord::Base 
    belongs_to :user 
end 

Затем создайте следующую таблицу:

create_table :users_users, :id => false do |t| 
    t.integer :followed_id 
    t.integer :follower_id 
end 

И вы комплект:

followed = User.find :first 
follower = User.find :last 

followed.followers << follower 

followed.followers.first.messages 
followed.followers.first.followers.first.messages # etc... 

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

Это должно быть возможно достичь путем добавления

has_and_belongs_to_many :followed_messages, :foreign_key => 'follower_id', 
    :class_name => 'Message', :association_foreign_key => 'followed_id' 

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

Update: Изменяя: class_name, она будет ассоциировать его с Message.id, не думать о том, что так не будет правильным в этом случае.

Таким образом, единственный «хороший» вариант - пройти через класс «Пользователь», как в первом примере. Единственные другие параметры, которые я вижу, - это либо расширения ассоциации (которые я не могу дать вам), либо, возможно, используя инструкцию finder.

has_many :followed_messages, :class_name => 'Message', 
    :finder_sql => 'select * from messages where user_id in(select followed_id from users_users where follower_id = #{id})' 

Вы, вероятно, придется настроить, что SQL заявление, чтобы получить все, чтобы работать, но, по крайней мере, вы должны получить картину :)

+0

has_and_belongs_to_many: followed_messages,: foreign_key => '', follower_id: class_name => 'сообщение',: association_foreign_key => 'followed_id' генерирует SQL: SELECT * FROM сообщений INNER JOIN следует за сообщением ON.ID = следует.followee_id WHERE (follows.follower_id = ) , но мне нужно, чтобы это было messages.user_id = follows.followee_id Есть ли способ сделать это? – Shalmanese

1

расположение Keijro была бы работать лучше, но если вам нужна таблица Follow, то вы можете выполнить SQL запрос, указанный следующим образом:

Follow.all(:joins => { :messages, :users }, :conditions => { "follows.follower_id" => current_user.id, "follows.followee_id" => "users.id", "users.id" => "messages.user_id"}) 
Смежные вопросы