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.