Rails has_and_belongs_to_many migration Rails has_and_belongs_to_many migration ruby-on-rails ruby-on-rails

Rails has_and_belongs_to_many migration


You need to add a separate join table with only a restaurant_id and user_id (no primary key), in alphabetical order.

First run your migrations, then edit the generated migration file.

Rails 3

rails g migration create_restaurants_users_table

Rails 4:

rails g migration create_restaurants_users

Rails 5

rails g migration CreateJoinTableRestaurantUser restaurants users

From the docs:

There is also a generator which will produce join tables if JoinTable is part of the name:


Your migration file (note the :id => false; it's what prevents the creation of a primary key):

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  endend

Rails 4

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

t.belongs_to will automatically create the necessary indices. def change will auto detect a forward or rollback migration, no need for up/down.

Rails 5

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

Note: There is also an option for a custom table name that can be passed as a parameter to create_join_table called table_name. From the docs

By default, the name of the join table comes from the union of the first two arguments provided to create_join_table, in alphabetical order. To customize the name of the table, provide a :table_name option:


The answers here are quite dated. As of Rails 4.0.2, your migrations make use of create_join_table.

To create the migration, run:

rails g migration CreateJoinTableRestaurantsUsers restaurant user

This will generate the following:

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  endend

If you want to index these columns, uncomment the respective lines and you're good to go!


When creating the join table, pay careful attention to the requirement that the two tables need to be listed in alphabetical order in the migration name/class. This can easily bite you if your model names are similar, e.g. "abc" and "abb". If you were to run

rails g migration create_abc_abb_table

Your relations will not work as expected. You must use

rails g migration create_abb_abc_table

instead.