Ruby on Rails通过自我引用的跟随/关注者关系

时间:2011-07-20 13:41:08

标签: ruby-on-rails activerecord

has_many上有很多帖子和帖子:通过,但我没有找到任何具体涵盖我正在尝试做的事情。

我有一个用户模型和一个友谊模型。用户有许多跟随他们的用户,以及许多关注者。这是通常的推特模式。

对于给定的用户,我想设置Active Record关系,该关系返回跟随用户并且用户是其关注者的实际用户。

这些是我设置的关系:

class User < ActiveRecord::Base

  has_many :following, :class_name => 'User', :through => :friendships, :foreign_key => 'user_id'

  has_many :followers, :class_name => 'User', :through => :friendships, :foreign_key => 'friend_id'

end

class Friendship < ActiveRecord::Base

  belongs_to :user
  belongs_to :following, :class_name => 'User', :foreign_key => 'friend_id'
  belongs_to :follower, :class_name => 'User', :foreign_key => 'user_id'

end

以下关系有效 - 它会生成以下联接:

SELECT `users`.* FROM `users` INNER JOIN `friendships` ON `users`.id = `friendships`.friend_id WHERE ((`friendships`.user_id = 1))

一切都很棒。

然而,追随者关系不起作用。我尝试了很多变化,但大多数似乎都返回了与结果相同的结果。

我需要按如下方式设置连接以返回正确的结果集。

SELECT `users`.* FROM `users` INNER JOIN `friendships` ON `users`.id = `friendships`.user_id WHERE ((`friendships`.friend_id = 1)); 

我哪里错了?

我可以使用has_many上的finder_sql选项进行设置,但似乎应该有更好的方法。

has_many :followers, :class_name => 'User', :finder_sql => 'SELECT `users`.* FROM `users` INNER JOIN `friendships` ON `users`.id = `friendships`.user_id WHERE ((`friendships`.friend_id = #{ id }))'

谢谢!


我取得了一些进展,最终通过将关系分成两部分来实现关系,如此回复所示:Self-referential has_many :through with customized :primary key issue

# FOLLOWING
has_many :friendships_to, :foreign_key => 'user_id', :class_name => 'Friendship'
has_many :following, :through => :friendships_to, :class_name => 'User'

# FOLLOWERS
has_many :friendships_from, :foreign_key => 'friend_id', :class_name => 'Friendship'
has_many :followers, :through => :friendships_from, :class_name => 'User'

但是,虽然可以使用关系的单行版本来跟随

has_many :following, :class_name => 'User', :through => :friendships, :foreign_key => 'user_id'

我仍然无法让它为粉丝工作。仍然想知道如何做到这一点?

2 个答案:

答案 0 :(得分:23)

您需要确保ActiveRecord知道User#friends和关注者的源关联,并指定ActiveRecord无法从关联名称推断的关系的类和foreign_key。

class Following < ActiveRecord::Base

  belongs_to :user
  belongs_to :followed, :class_name => 'User'

end

class User < ActiveRecord::Base

  has_many :followings
  has_many :friends, :through => :followings, :source => 'followed'

  has_many :followeds, :class_name => 'Following', :foreign_key => 'followed_id'
  has_many :followers, :through => :followeds, :source => :user

end

答案 1 :(得分:5)

我在学习过程中有点像菜鸟,但这个模型对我来说似乎更清晰:

class User < ActiveRecord::Base
  has_many :followings
  has_many :followers, through: :followings
end

class Following < ActiveRecord::Base
  belongs_to :user
  belongs_to :follower, class_name: 'User'
end