Обратная связь в соединительной таблице - PullRequest
2 голосов
/ 20 января 2012

У меня есть модель дружбы пользователей, для которой я хочу написать поиск для

- это отношение habtm, называемое peers, связывающее 2 пользователей вместе.Связь - это одно соединение (Джо <-> Стив, а не Джо -> Стив и Стив -> Джо).

Моя таблица соединений выглядит следующим образом: user_id peer_id

Оба хранят пользователяидентификатор в отношениях.Ниже приведен HABTM для пользователя.

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

Я пытаюсь выяснить искатель sql, который позволит этой записи в объединяющей таблице показывать обе стороны.user_id = steve.id peer_id = joe.id

, чтобы показать отношения, когда я вызываю joe.peers и steve.peers.В настоящее время steve.peers возвращает joe, но joe.peers ничего не показывает.

Ответы [ 2 ]

2 голосов
/ 20 января 2012

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

1 голос
/ 20 января 2012

Вы могли бы просто написать 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

Но подход Тадмана более умный с точки зрения целостности данных и больше соответствует тому, что вам скажет администратор БД.(см. мой комментарий к вашему вопросу)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...