【问题标题】:Ruby on Rails has_many through self-referential following/follower relationshipsRuby on Rails has_many 通过自引用的追随者/追随者关系
【发布时间】:2011-07-20 13:41:07
【问题描述】:

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

我有一个用户模型和一个友谊模型。一个用户有很多关注他们的用户,以及很多关注者。这是通常的 Twitter 模型。

对于给定的用户,我想设置 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))

一切都是伟大的。

但是,Follower 关系不起作用。我尝试了许多变体,但大多数似乎返回的结果集与以下相同。

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

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'

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

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    您需要确保 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
    

    【讨论】:

      【解决方案2】:

      我在学习过程中有点菜鸟,但这些模型对我来说似乎更干净:

      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
      

      【讨论】:

      • 这个答案假设追随是相互的,而在 Twitter 模型中并非如此。
      猜你喜欢
      • 2019-07-03
      • 2017-12-08
      • 2021-10-09
      • 1970-01-01
      • 1970-01-01
      • 2021-06-13
      • 1970-01-01
      • 1970-01-01
      • 2017-12-17
      相关资源
      最近更新 更多