Rails has_and_belongs_to_many миграция - PullRequest
112 голосов
/ 03 июля 2011

У меня есть две модели restaurant и user, для которых я хочу выполнить отношение has_and_belongs_to_many.

Я уже вошел в файлы модели и добавил has_and_belongs_to_many :restaurants и has_and_belongs_to_many :users

Я предполагаю, что на этом этапе я смогу сделать что-то подобное с Rails 3:

rails generate migration ....

но все, что я пробовал, похоже, провалилось. Я уверен, что это что-то действительно простое, я новичок в рельсах, поэтому я все еще учусь.

Ответы [ 4 ]

237 голосов
/ 03 июля 2011

Вам нужно добавить отдельную таблицу соединений только с restaurant_id и user_id (без первичного ключа) в в алфавитном порядке .

Сначала запустите миграцию, затем отредактируйтесгенерированный файл миграции.

Рельсы 3

rails g migration create_restaurants_users_table

Рельсы 4 :

rails g migration create_restaurants_users

Рельсы 5

rails g migration CreateJoinTableRestaurantUser restaurants users

Из документов :

Существует также генератор, который будет создавать таблицы соединений, если JoinTable является частью имени:


Ваш файл миграции (обратите внимание на :id => false; это то, что предотвращает создание первичного ключа):

Rails 3

class CreateRestaurantsUsers < ActiveRecord::Migration
  def self.up
    create_table :restaurants_users, :id => false do |t|
        t.references :restaurant
        t.references :user
    end
    add_index :restaurants_users, [:restaurant_id, :user_id]
    add_index :restaurants_users, :user_id
  end

  def self.down
    drop_table :restaurants_users
  end
end

Рельсы 4

class CreateRestaurantsUsers < ActiveRecord::Migration
  def change
    create_table :restaurants_users, id: false do |t|
      t.belongs_to :restaurant
      t.belongs_to :user
    end
  end
end

t.belongs_to автоматически создадут необходимые индексы.def change автоматически обнаружит миграцию вперед или откат, нет необходимости в повышении / понижении.

Rails 5

create_join_table :restaurants, :users do |t|
  t.index [:restaurant_id, :user_id]
end

Примечание. Существует также опция дляпроизвольное имя таблицы, которое можно передать в качестве параметра в create_join_table с именем table_name.Из документов

По умолчанию имя таблицы объединения происходит из объединения первых двух аргументов, предоставленных для create_join_table, в алфавитном порядке.Чтобы настроить имя таблицы, укажите параметр: table_name:

30 голосов
/ 16 февраля 2016

Ответы здесь довольно устарели.Начиная с Rails 4.0.2, ваши миграции используют create_join_table.

. Чтобы создать миграцию, запустите:

rails g migration CreateJoinTableRestaurantsUsers restaurant user

. Это создаст следующее:

class CreateJoinTableRestaurantsUsers < ActiveRecord::Migration
  def change
    create_join_table :restaurants, :users do |t|
      # t.index [:restaurant_id, :user_id]
      # t.index [:user_id, :restaurant_id]
    end
  end
end

Если вы хотите проиндексировать эти столбцы, раскомментируйте соответствующие строки и все готово!

24 голосов
/ 27 мая 2013

При создании таблицы объединения обратите особое внимание на требование, чтобы две таблицы были перечислены в в алфавитном порядке в имени / классе миграции. Это может легко укусить вас, если названия вашей модели похожи, например, "abc" и "abb". Если бы вы должны были бежать

rails g migration create_abc_abb_table

Ваши отношения будут не работать, как ожидалось. Вы должны использовать

rails g migration create_abb_abc_table

вместо.

6 голосов
/ 03 июля 2011

Для отношений HABTM вам необходимо создать таблицу соединений. Существует только таблица соединения, и в этой таблице не должно быть столбца идентификатора. Попробуйте эту миграцию.

def self.up
  create_table :restaurants_users, :id => false do |t|
    t.integer :restaurant_id
    t.integer :user_id
  end
end

def self.down
  drop_table :restaurants_users
end

Вы должны проверить это руководство по рельсам отношений

...