Rails: create_join_table sollte Indizes und Fremdschlüsselbeschränkungen enthalten

Erstellt am 7. Jan. 2016  ·  3Kommentare  ·  Quelle: rails/rails

Wenn man derzeit eine Join-Tabelle wie folgt generiert:

rails g migration create_join_table_showroom_user showroom user

die folgende Migration wird erstellt:

class CreateJoinTableShowroomUser < ActiveRecord::Migration
  def change
    create_join_table :showrooms, :users do |t|
      # t.index [:showroom_id, :user_id]
      # t.index [:user_id, :showroom_id]
    end
  end
end

Wenn Sie diese Migration direkt ausführen, wird eine sehr einfache Join-Tabelle erstellt:

create_table "showrooms_users", id: false, force: :cascade do |t|
  t.integer "showroom_id", null: false
  t.integer "user_id",     null: false
end

Also keine Indizes, keine Fremdschlüssel etc. Entkommentiert man die beiden Zeilen bei der Migration, erhält man nun:

create_table "showrooms_users", id: false, force: :cascade do |t|
  t.integer "showroom_id", null: false
  t.integer "user_id",     null: false
end

add_index "showrooms_users", ["showroom_id", "user_id"], name: "index_showrooms_users_on_showroom_id_and_user_id", using: :btree
add_index "showrooms_users", ["user_id", "showroom_id"], name: "index_showrooms_users_on_user_id_and_showroom_id", using: :btree

Ich würde argumentieren, dass die generierte Migration so aussehen sollte:

class CreateJoinTableShowroomUser < ActiveRecord::Migration
  def change
    create_join_table :showrooms, :users do |t|
      # t.references :showroom, index: true, null: false, foreign_key: true
      # t.references :user, index: true, null: false, foreign_key: true
      # t.index [:showroom_id, :user_id]
      # t.index [:user_id, :showroom_id]
    end
  end
end

Wenn man die beiden references Zeilen auskommentiert, sieht die erzeugte Tabelle so aus:

create_table "showrooms_users", id: false, force: :cascade do |t|
  t.integer "showroom_id", null: false
  t.integer "user_id",     null: false
end

add_index "showrooms_users", ["showroom_id"], name: "index_showrooms_users_on_showroom_id", using: :btree
add_index "showrooms_users", ["user_id"], name: "index_showrooms_users_on_user_id", using: :btree

add_foreign_key "showrooms_users", "showrooms"
add_foreign_key "showrooms_users", "users"

Warum möchte jemand keine Fremdschlüssel und Indizes in einer Join-Tabelle haben? @rafaelfranca

activerecord

Hilfreichster Kommentar

Ich weiß nicht, die Migrationen verwenden solche Optionen meistens nicht. Sie können den Index bereits mit :index aktivieren. Also läuft

rails g migration create_join_table_showroom_user showroom:index user:index

Produziert

class CreateJoinTableShowroomUser < ActiveRecord::Migration
  def change
    create_join_table :showrooms, :users do |t|
      t.index [:showroom_id, :user_id]
      t.index [:user_id, :showroom_id]
    end
  end
end

Außerdem können Sie beim Erstellen von Modellen Referenzen verwenden, um einen Index zu erstellen. Wie so:

rails g migration CreatePost title:string user:references:index

Was produziert:

class CreatePost < ActiveRecord::Migration
  def change
    create_table :posts do |t|
      t.string :title
      t.references :user, index: true, foreign_key: true
    end
  end
end

Vielleicht wäre es also am besten, etwas zuzulassen wie:

rails g migration create_join_table_showroom_user showroom:references:index user:references:index

Erstellen Sie dies:

class CreateJoinTableShowroomUser < ActiveRecord::Migration
  def change
    create_join_table :showrooms, :users do |t|
      t.references :showroom, index: true, foreign_key: true
      t.references :user, index: true, foreign_key: true
      # t.index [:showroom_id, :user_id]
      # t.index [:user_id, :showroom_id]
    end
  end
end

Und dann würde die Standardeinstellung rails g migration create_join_table_showroom_user showroom user Folgendes erzeugen:

class CreateJoinTableShowroomUser < ActiveRecord::Migration
  def change
    create_join_table :showrooms, :users do |t|
      # t.references :showroom, index: true, foreign_key: true
      # t.references :user, index: true, foreign_key: true
      # t.index [:showroom_id, :user_id]
      # t.index [:user_id, :showroom_id]
    end
  end
end

Alle 3 Kommentare

Ich stimme zu! Ich muss das die ganze Zeit machen. Vielleicht könnten wir dem Generator Optionen hinzufügen, wie zum Beispiel:
rails g migration ... --fk --idx
oder sie standardmäßig einschließen und Optionen zum Deaktivieren haben, wie zum Beispiel:
rails g migration ... --no_fk --no_idx

Ich weiß nicht, die Migrationen verwenden solche Optionen meistens nicht. Sie können den Index bereits mit :index aktivieren. Also läuft

rails g migration create_join_table_showroom_user showroom:index user:index

Produziert

class CreateJoinTableShowroomUser < ActiveRecord::Migration
  def change
    create_join_table :showrooms, :users do |t|
      t.index [:showroom_id, :user_id]
      t.index [:user_id, :showroom_id]
    end
  end
end

Außerdem können Sie beim Erstellen von Modellen Referenzen verwenden, um einen Index zu erstellen. Wie so:

rails g migration CreatePost title:string user:references:index

Was produziert:

class CreatePost < ActiveRecord::Migration
  def change
    create_table :posts do |t|
      t.string :title
      t.references :user, index: true, foreign_key: true
    end
  end
end

Vielleicht wäre es also am besten, etwas zuzulassen wie:

rails g migration create_join_table_showroom_user showroom:references:index user:references:index

Erstellen Sie dies:

class CreateJoinTableShowroomUser < ActiveRecord::Migration
  def change
    create_join_table :showrooms, :users do |t|
      t.references :showroom, index: true, foreign_key: true
      t.references :user, index: true, foreign_key: true
      # t.index [:showroom_id, :user_id]
      # t.index [:user_id, :showroom_id]
    end
  end
end

Und dann würde die Standardeinstellung rails g migration create_join_table_showroom_user showroom user Folgendes erzeugen:

class CreateJoinTableShowroomUser < ActiveRecord::Migration
  def change
    create_join_table :showrooms, :users do |t|
      # t.references :showroom, index: true, foreign_key: true
      # t.references :user, index: true, foreign_key: true
      # t.index [:showroom_id, :user_id]
      # t.index [:user_id, :showroom_id]
    end
  end
end

+1 @erullmann Das ist eine sehr schöne Lösung. :smiley:

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen