Rails: схема самосоединения с has_and_belongs_to_many?

Я хотел бы создать структуру Users, имеющую много friends, также класса User:

class User < ActiveRecord::Base
  has_and_belongs_to_many :friends, class_name: "User"
end

Мне не нужны детали их отношений, поэтому я не использую :through с видом класса Friendship. Но теперь я не могу найти способ создания соответствующей базы данных (ни с помощью файла миграции, ни с помощью команды rails g model User username:string ...). Любые идеи?

Ответ 1

Вот некоторые ресурсы, которые могут быть полезны:

Я обобщу информацию, найденную в этих ссылках:

Учитывая, что вы описываете взаимосвязь "многие-ко-многим" с самореферментом, вы, конечно же, получите таблицу соединений. Обычно таблицу соединений следует назначать так, чтобы Rails автоматически определял, к каким моделям присоединяется таблица, однако "самореферентная" часть делает это немного неудобным, но не сложным. Вам просто нужно указать имя таблицы соединений, а также столбцы соединения.

Вам нужно создать эту таблицу, используя миграцию, которая, вероятно, будет выглядеть примерно так:

class CreateFriendships < ActiveRecord::Migration
  def self.up
    create_table :friendships, id: false do |t|
      t.integer :user_id
      t.integer :friend_user_id
    end

    add_index(:friendships, [:user_id, :friend_user_id], :unique => true)
    add_index(:friendships, [:friend_user_id, :user_id], :unique => true)
  end

  def self.down
      remove_index(:friendships, [:friend_user_id, :user_id])
      remove_index(:friendships, [:user_id, :friend_user_id])
      drop_table :friendships
  end
end

Я не уверен, есть ли ярлык для создания этой таблицы, но как минимум вы можете просто сделать rails g migration create_friendships и заполнить методы self.up и self.down.

И наконец, в вашей модели пользователя вы просто добавляете имя таблицы соединений, например:

class User < ActiveRecord::Base
  has_and_belongs_to_many :friends, 
              class_name: "User", 
              join_table: :friendships, 
              foreign_key: :user_id, 
              association_foreign_key: :friend_user_id
end

Как вы можете видеть, хотя в базе данных есть таблица соединений, нет соответствующей модели соединения.

Пожалуйста, дайте мне знать, работает ли это для вас.