Rails: Join model table migration template

When creating a database table for a join model without further importance, you can use Rails' create_join_table:

class CreateSchoolsStudents < ActiveRecord::Migration[7.2]
  def change
    create_join_table :schools, :students, column_options: { foreign_key: true } do |t|
      # t.timestamps # Optional
      t.index [:student_id, :school_id], unique: true
    end
  end
end

This will create a table without an id column and without timestamps. It will have school_id and student_id columns with null: false constraints and indexes.

  • null: false prevents creation of join records without associations.
  • The foreign_key: true prevents deletion of a joined record. Set dependent: :destroy on your has_many :schools_students association in both models to remove join records together with their model records.
  • The optional unique index prevents duplicate join records.

More control

If you need more flexibility, e.g. the table models a distinct entity, write your migration like this:

class CreateSchoolsStudents < ActiveRecord::Migration[7.2]
  def change
    create_table :schools_students do |t|
      t.timestamps
      
      # More columns ...

      t.references :student, null: false, foreign_key: true
      t.references :school, null: false, foreign_key: true
      
      t.index [:student_id, :school_id], unique: true
    end
  end
end

t.references automatically adds an index. If you're using the compound index at the end, you can avoid a duplicate index by calling t.references :student with index: false.

Dominik Schöler