Rails has_and_belongs_to_many migration

前端 未结 4 1156
广开言路
广开言路 2020-12-04 05:56

I have two models restaurant and user that I want to perform a has_and_belongs_to_many relationship.

I have already gone into the model fil

相关标签:
4条回答
  • 2020-12-04 06:06

    For HABTM relationships, you need to create a join table. There is only join table and that table should not have an id column. Try this migration.

    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
    

    You must check this relationship rails guide tutorials

    0 讨论(0)
  • 2020-12-04 06:13

    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
      end
    end
    

    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
      end
    end
    

    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:

    0 讨论(0)
  • 2020-12-04 06:29

    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
      end
    end
    

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

    0 讨论(0)
  • 2020-12-04 06:29

    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.

    0 讨论(0)
提交回复
热议问题