Ruby on Rails has_many 通过自我引用的跟随/跟随关系 [英] Ruby on Rails has_many through self-referential following/follower relationships

查看:17
本文介绍了Ruby on Rails has_many 通过自我引用的跟随/跟随关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

has_many :through 上有许多帖子和主题,但我还没有找到任何专门涵盖我正在尝试做的事情的帖子和主题.

There are a number of posts and threads on has_many :through, but I haven't found any that cover specifically what I'm trying to do.

我有一个 User 模型和一个 Friendships 模型.一个用户有很多关注他们的用户,也有很多关注者.这是通常的 Twitter 模型.

I have a User model and a Friendships model. A user has many users that are following them, as well as many followers. It is the usual Twitter model.

对于给定的用户,我想设置 Active Record 关系,以返回关注该用户以及该用户是其关注者的实际用户.

For a given user, I want to setup Active Record relationships that return the actual users that are following the user and that the user is a follower of.

这些是我建立的关系:

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

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

The Following relationship works - it generates the below join:

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

一切都很美好.

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

However, the Follower relationship does not work. I've tried a number of variations, but most seem to return the same set of results as Following.

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

I need the join to be setup as follows to return the correct result set.

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

我哪里出错了?

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

I can set this up using the finder_sql option on the has_many, but it seems like there should be a better way.

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 }))'

谢谢!

我取得了一些进展,最终通过将关系分成两部分来建立关系,如以下回复所示:自引用 has_many :through 自定义:primary key issue

I made a bit of progress and finally got the relationship working by breaking the relationships into two parts, as was shown in this response: 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'

然而,虽然可以有一个单行版本的关系用于后续

However, while it was possible to have a one-line version of the relationship for following

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

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

I still wasn't able to get it to work for followers. Still wondering how this could be done?

推荐答案

您需要确保 ActiveRecord 知道 User#friends 和关注者的源关联,并为 ActiveRecord 可以的关系指定 class 和 foreign_key't 从关联名称推断.

You need to make sure ActiveRecord knows what the source association for the User#friends and likewise the followers and specify the class and foreign_key for the relationships that ActiveRecord can't extrapolate from the association names.

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

这篇关于Ruby on Rails has_many 通过自我引用的跟随/跟随关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆