Обычно отношения лучше всего выражать как односторонние или как пара односторонних отношений. Это связано с тем, что в большинстве реляционных баз данных легко установить отношение 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
, поскольку это должно давать идентичные результаты, если вы сохраняете целостность данных.