Method: ActiveRecord::ConnectionAdapters::SchemaStatements#create_join_table

Defined in:
activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb

#create_join_table(table_1, table_2, column_options: {}, **options) ⇒ Object

Creates a new join table with the name created using the lexical order of the first two arguments. These arguments can be a String or a Symbol.

# Creates a table called 'assemblies_parts' with no id.
create_join_table(:assemblies, :parts)

# Creates a table called 'paper_boxes_papers' with no id.
create_join_table('papers', 'paper_boxes')

A duplicate prefix is combined into a single prefix. This is useful for namespaced models like Music::Artist and Music::Record:

# Creates a table called 'music_artists_records' with no id.
create_join_table('music_artists', 'music_records')

See connection.add_reference for details of the options you can use in column_options. column_options will be applied to both columns.

You can pass an options hash which can include the following keys:

:table_name

Sets the table name, overriding the default.

:options

Any extra options you want appended to the table definition.

:temporary

Make a temporary table.

:force

Set to true to drop the table before creating it. Defaults to false.

Note that #create_join_table does not create any indices by default; you can use its block form to do so yourself:

create_join_table :products, :categories do |t|
  t.index :product_id
  t.index :category_id
end
Add foreign keys with delete cascade
create_join_table(:assemblies, :parts, column_options: { foreign_key: { on_delete: :cascade } })

generates:

CREATE TABLE assemblies_parts (
  assembly_id bigint NOT NULL,
  part_id bigint NOT NULL,
  CONSTRAINT fk_rails_0d8a572d89 FOREIGN KEY ("assembly_id") REFERENCES "assemblies" ("id") ON DELETE CASCADE,
  CONSTRAINT fk_rails_ec7b48402b FOREIGN KEY ("part_id") REFERENCES "parts" ("id") ON DELETE CASCADE
)
Add a backend specific option to the generated SQL (MySQL)
create_join_table(:assemblies, :parts, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8')

generates:

CREATE TABLE assemblies_parts (
  assembly_id bigint NOT NULL,
  part_id bigint NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8


408
409
410
411
412
413
414
415
416
417
418
419
420
# File 'activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb', line 408

def create_join_table(table_1, table_2, column_options: {}, **options)
  join_table_name = find_join_table_name(table_1, table_2, options)

  column_options.reverse_merge!(null: false, index: false)

  t1_ref, t2_ref = [table_1, table_2].map { |t| reference_name_for_table(t) }

  create_table(join_table_name, **options.merge!(id: false)) do |td|
    td.references t1_ref, **column_options
    td.references t2_ref, **column_options
    yield td if block_given?
  end
end