Ruby on Rails:是否可以 :include 循环连接表的另一条腿?

发布于 2024-08-23 21:27:04 字数 1282 浏览 10 评论 0原文

我正在开发一个模拟用户之间友谊的应用程序。

class User
  has_many :friendships
  has_many :friends, 
           :through => :friendships,
           :conditions => "status = #{Friendship::FULL}"
end
class Friendship
  belongs_to :user
  belongs_to :friend, :class_name => "User", :foreign_key => "friend_id"
end

当两个用户成为朋友时,会创建友谊类的两个实例,每个友谊方向一个实例。这是必要的,因为可以在每个方向设置不同的权限,而且也是为了便于查找,因此我们始终通过 user_id 进行搜索,而无需创建第二个索引并需要加倍搜索。

是否有可能使用 find 或命名范围来拉出一个朋友以及反友谊?我想这样做是因为我允许用户编辑存储在他们自己的友谊分支中的友谊权限,因此当我向用户显示朋友的信息时,我需要检查相反的分支来查看权限是如何设置的。 (顺便说一句,这看起来是一个合乎逻辑的做事方式吗?要么你存储到对面,要么你必须在展示之前咨询对面,这两种方式都令人不愉快。)

我已经成功地制作了一批完成这项工作的 SQL 语句:

def self.secure_friends(user_id)
  User.find_by_sql("SELECT u.*, cf.permissions
                    FROM users u 
                    INNER JOIN friendships f ON u.id = f.friend_id 
                    INNER JOIN friendships cf ON u.id = cf.user_id AND cf.friend_id = #{user_id} 
                    WHERE ((f.user_id = #{user_id}) AND (f.status = #{Friendship::FULL}))")
end

该函数返回用户的所有好友姓名和 ID,以及权限。然而,这看起来确实不太理想,意味着我必须通过调用friend.permissions来访问权限,其中权限实际上并不是friend的成员,而只是由find_by_sql作为属性合并进来。总而言之,我真的宁愿使用named_scope或find调用来做到这一点,但不幸的是,我使用该方法所做的每一次尝试都导致了错误,因为Rails因将相同的友谊连接表连接到而感到窒息查询两次。

I'm working on an application that models friendships between users.

class User
  has_many :friendships
  has_many :friends, 
           :through => :friendships,
           :conditions => "status = #{Friendship::FULL}"
end
class Friendship
  belongs_to :user
  belongs_to :friend, :class_name => "User", :foreign_key => "friend_id"
end

When two users become friends, two instances of the friendship class are created, one for each direction of the friendship. This is necessary because different permissions can be set in each direction, and also for ease of lookups so we always search by the user_id without creating a second index and needing to double up searches.

Is it possible, using either find or a named scope to pull up a friend along with the counter-friendship? I'd like to do this because I'm allowing users to edit friendship permissions which are stored in their own leg of the friendship, and thus when I'm displaying a friend's info to the user I need to check the opposite leg to see how permissions are set. (As an aside, does this seem like a logical way to do things? Either you store into the opposite side, or you have to consult the opposite side before display, both kind of unpleasant.)

I've managed to whip up a batch of SQL that does the job:

def self.secure_friends(user_id)
  User.find_by_sql("SELECT u.*, cf.permissions
                    FROM users u 
                    INNER JOIN friendships f ON u.id = f.friend_id 
                    INNER JOIN friendships cf ON u.id = cf.user_id AND cf.friend_id = #{user_id} 
                    WHERE ((f.user_id = #{user_id}) AND (f.status = #{Friendship::FULL}))")
end

The function returns all of a user's friends names and ids, along with the permissions. However, this really doesn't seem ideal, and means I have to access the permissions by calling friend.permissions, where permissions isn't actually a member of friend but is just merged in as an attribute by find_by_sql. All in all, I'd really rather be doing this with a named_scope or a find call, but unfortunately, every attempt I've made to use that approach has resulted in errors as Rails chokes on having the same Friendship join table getting joined to the query twice.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

薄凉少年不暖心 2024-08-30 21:27:04

我不确定你想要做多少事情,以及你允许插件做多少事情——但我使用这个 has_many_friends 插件取得了巨大成功:has_many_friends 插件位于 Github

您可以查看源代码并受到启发...只需要一个友谊模型,其中包含以下内容:

belongs_to :friendshipped_by_me,   :foreign_key => "user_id",   :class_name => "User"
belongs_to :friendshipped_for_me,  :foreign_key => "friend_id", :class_name => "User"

然后在您的用户类中,有:

has_many :friends_by_me,
         :through => :friendships_by_me,
         :source => :friendshipped_for_me

或者,只是

/app/models/user

has_many_friends

稍后:

@current_user.friends.each{|friend| friend.annoy!}

I'm not sure how much you want to do, and how much you'd allow a plugin to do -- but I've used this has_many_friends plugin with great success: has_many_friends plugin at Github

You can look at the source and be inspired... Just need a Friendship model that has things like:

belongs_to :friendshipped_by_me,   :foreign_key => "user_id",   :class_name => "User"
belongs_to :friendshipped_for_me,  :foreign_key => "friend_id", :class_name => "User"

and then later, in your user class, have:

has_many :friends_by_me,
         :through => :friendships_by_me,
         :source => :friendshipped_for_me

Or, just

/app/models/user

has_many_friends

Later:

@current_user.friends.each{|friend| friend.annoy!}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文