我有一个用户友谊模型,我想为
编写查找是一种称为同伴的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什么都没有显示。
答案 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告诉您的内容。 (见我对你问题的评论)