Ассоциации «многие ко многим» в одной модели (рельсы)

Допустим, у меня есть следующая таблица пользователей

идентификатор, тип
1, "A"
2, "B"
3, "B"
4, "A"
5, "B"
6, "A "

Есть два типа пользователей. Пользователи «А» и пользователи «Б». «А» может быть связано со многими «Б», а «Б» может быть связано со многими «А». Допустим, у нас есть следующая таблица «соединений»

id, A_id, B_id

1, 1, 2
2, 4, 2
3, 4, 3
4, 6, 5
5, 1, 5
6, 4, 5

Что будет представлять следующий график:

график подключений

У меня могла бы быть таблица «A», в которой хранятся индексы external_key пользователей с типом «A» (т. е. «эти пользователи имеют тип «A»), и аналогично для «B», и в этом случае я мог бы просто определить простая ассоциация has_many через таблицу соединений от «А» к «Б» и наоборот.

Я хочу иметь возможность напечатать что-то вроде a.b, чтобы создать все «B», с которыми связано «a», а также b.a, чтобы создать все «A», с которыми связано «b».

Мой вопрос: может ли эта ассоциация «многие ко многим» между «A» и «B» быть определена с использованием вместо этого одной модели пользователя? Можно ли использовать самосоединение?

Спасибо за уделенное время


person user2205763    schedule 22.05.2013    source источник
comment
Идет ли этот Railscast в нужном вам направлении? Если нет, то что может служить реальным примером для вашего объекта модели и отношений между ними?   -  person Thomas Klemm    schedule 23.05.2013
comment
возможный дубликат Как работают методы ассоциации рельсов?   -  person user2205763    schedule 10.08.2014


Ответы (1)


Выглядит как довольно стандартный пример has_many :through и STI.

Данный:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :type

      t.timestamps
    end
  end
end

class CreateConnections < ActiveRecord::Migration
  def change
    create_table :connections do |t|
      t.integer :a_user_id
      t.integer :b_user_id

      t.timestamps
    end
  end
end

class User < ActiveRecord::Base
end

class AUser < User
  has_many :connections
  has_many :b_users, :through => :connections
end

class BUser < User
  has_many :connections
  has_many :a_users, :through => :connections
end

class Connection < ActiveRecord::Base
  belongs_to :a_user
  belongs_to :b_user
end

Когда (выходные данные консоли rails обрезаны для краткости):

>> a_user = AUser.create!
>> b_user = BUser.create!
>> connection = a_user.connections.build
>> connection.b_user = b_user
>> connection.save!

Потом:

>> a_user.b_users
=> ActiveRecord::Associations::CollectionProxy of BUsers

Если ваши объекты AUser и BUser будут иметь разные наборы атрибутов, вам следует использовать полиморфные ассоциации вместо этого, что требует создания еще пары таблиц, но на самом деле не сильно усложняет ситуацию.

person James    schedule 23.05.2013