Rails migration for has_and_belongs_to_many join table

后端 未结 6 1408
花落未央
花落未央 2020-11-29 15:40

How do I do a script/generate migration to create a join table for a has_and_belongs_to_many relationship?

The application runs on Rails 2.

相关标签:
6条回答
  • 2020-11-29 16:22

    Where:

    class Teacher < ActiveRecord::Base
      has_and_belongs_to_many :students
    end
    

    and

    class Student < ActiveRecord::Base
      has_and_belongs_to_many :teachers
    end
    

    for rails 4:

    rails generate migration CreateJoinTableStudentTeacher student teacher
    

    for rails 3:

    rails generate migration students_teachers student_id:integer teacher_id:integer
    

    for rails < 3

    script/generate migration students_teachers student_id:integer teacher_id:integer
    

    (note the table name lists both join tables in alphabetical order)

    and then for rails 3 and below only, you need to edit your generated migration so an id field is not created:

    create_table :students_teachers, :id => false do |t|
    
    0 讨论(0)
  • 2020-11-29 16:25

    In rails 4, you can simple use

    create_join_table :table1s, :table2s

    it is all.

    Caution: you must offord table1, table2 with alphanumeric.

    0 讨论(0)
  • 2020-11-29 16:31

    The top answer shows a composite index that I don't believe will be used to lookup apples from oranges.

    create_table :apples_oranges, :id => false do |t|
      t.references :apple, :null => false
      t.references :orange, :null => false
    end
    
    # Adding the index can massively speed up join tables.
    # This enforces uniqueness and speeds up apple->oranges lookups.
    add_index(:apples_oranges, [:apple_id, :orange_id], :unique => true)
    # This speeds up orange->apple lookups
    add_index(:apples_oranges, :orange_id)
    

    I did find the answer this is based on by 'The Doctor What' useful and the discussion certainly so too.

    0 讨论(0)
  • 2020-11-29 16:33

    A has_and_belongs_to_many table must match this format. I'm assuming the two models to be joined by has_and_belongs_to_many are already in the DB : apples and oranges:

    create_table :apples_oranges, :id => false do |t|
      t.references :apple, :null => false
      t.references :orange, :null => false
    end
    
    # Adding the index can massively speed up join tables. Don't use the
    # unique if you allow duplicates.
    add_index(:apples_oranges, [:apple_id, :orange_id], :unique => true)
    

    If you use the :unique => true on the index, then you should (in rails3) pass :uniq => true to has_and_belongs_to_many.

    More information: Rails Docs

    UPDATED 2010-12-13 I've updated it to remove the id and timestamps... Basically MattDiPasquale and nunopolonia are correct: There must not be an id and there must not be timestamps or rails won't allow has_and_belongs_to_many to work.

    0 讨论(0)
  • 2020-11-29 16:35

    I like doing:

    rails g migration CreateJoinedTable model1:references model2:references. That way I get a migration that looks like this:

    class CreateJoinedTable < ActiveRecord::Migration
      def change
        create_table :joined_tables do |t|
          t.references :trip, index: true
          t.references :category, index: true
        end
        add_foreign_key :joined_tables, :trips
        add_foreign_key :joined_tables, :categories
      end
    end
    

    I like having index on these columns because I'll often be doing lookups using these columns.

    0 讨论(0)
  • 2020-11-29 16:44

    You should name the table the names of 2 models you want to connect by alphabetical order and put the two model id's in the table. Then connect each model to each other creating the associations in the model.

    Here's an example:

    # in migration
    def self.up
      create_table 'categories_products', :id => false do |t|
        t.column :category_id, :integer
        t.column :product_id, :integer
      end
    end
    
    # models/product.rb
    has_and_belongs_to_many :categories
    
    # models/category.rb
    has_and_belongs_to_many :products
    

    But this is not very flexible and you should think about using has_many :through

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