连接表中的反向关系

时间:2012-01-20 16:43:57

标签: mysql ruby-on-rails database activerecord

我有一个用户友谊模型,我想为

编写查找

是一种称为同伴的habtm关系,将2个用户联系在一起。关系是一个单一的联系(Joe< - > Steve,而不是Joe - > Steve和Steve - > Joe)。

我的联接表如下: 用户身份 的peer_id

两者都在关系中存储用户ID。以下是用户的HABTM。

has_and_belongs_to_many :peers, class_name: 'User', 
foreign_key: 'user_id', association_foreign_key: 'peer_id', 
join_table: 'users_peers'

我试图找出finder sql,它将允许连接表中的这条记录显示双方。 user_id = steve.id peer_id = joe.id

显示我调用joe.peers和steve.peers时的关系。目前,steve.peers返回joe,但是joe.peers什么都没有显示。

2 个答案:

答案 0 :(得分:2)

一般来说,关系最好用单向或单向关系表示。这是因为在大多数关系数据库中,很容易建立A到B或B到A的关系,但不能同时建立一个记录。你基本上需要两个查询,除非你做了很多假设和黑客攻击。

根据我的经验,使用has_and_belongs_to_many并不会让你的生活变得更轻松,因为它是Rails 1.0中的遗物,并不像取代它的has_many :through方法那么好。在你的情况下,这将是如何发挥作用:

class Node < ActiveRecord::Base
  has_many :peers_of,
    :class_name => 'Peer',
    :foreign_key => :of_user_id

  has_many :peers_to,
    :class_name => 'Peer',
    :foreign_key => :to_user_id

  has_many :peers,
    :through => :peers_of,
    :source => :to_user

  has_many :peers_with,
    :through => :peers_to,
    :source => :of_user
end

class Peer < ActiveRecord::Base
  belongs_to :of_user,
    :class_name => 'User'
  belongs_to :to_user,
    :class_name => 'User'
end

语义变得有点混乱,所以你可能想要调整它们。这里的想法是在添加“对等”时建立双向关系,其中包括一对A-> B和B-> A记录。

出于查询的目的,您只需获取@user.peers,而不必担心peers_with反向关系,因为如果您保持数据完整性,则会产生相同的结果。< / p>

答案 1 :(得分:1)

你可以手工编写sql:

class PeerRelation
  belongs_to :user1, :class_name=>"User"
  belongs_to :user2, :class_name=>"User"
end

class User

  def set_peer(user)
     user1_id, user2_id = [self.id, user.id].sort
     PeerRelation.find_or_create_by_user1_id_and_user2_id(user1_id, user2_id)
  end

  def peers
    User.joins("inner join peer_relations on 
                  peer_relations.user1_id = #{self.id} or
                  peer_relations.user2_id = #{self.id}")

  end
end

但从数据完整性的角度来看,tadman的方法更为智能,并且更符合DBA告诉您的内容。 (见我对你问题的评论)