2009-05-04 55 views
1

我建立一个小的Twitter微博式的服务,用户可以跟随其他用户,并得到他们的消息的饲料多个连接在轨使用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' 

用户类来实现,但我不知道这样会怎样正确的是。或者有可能通过关联扩展来实现,但在那里我无法给出任何例子。

更新: 通过改变:CLASS_NAME,它将与Message.id它联系起来,没想到这一点,所以它不会在这种方式是正确的。

所以唯一的“不错”选择就是像第一个例子那样通过User类。 我能看到的唯一的其他选项是关联扩展(我不能给你一个例子)或者可能使用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查询SQL: SELECT * FROM消息INNER JOIN跟在ON messages.id =后面。followee_id WHERE(follows.follower_id = ) ,但我需要它是 messages.user_id = follows.followee_id 有没有办法做到这一点? – Shalmanese 2009-05-10 09:10:31

1

Keijro的安排会更好地工作,但如果你需要后续表,然后

Follow.all(:joins => { :messages, :users }, :conditions => { "follows.follower_id" => current_user.id, "follows.followee_id" => "users.id", "users.id" => "messages.user_id"})