# 目的
railsのマイグレーションで外部キーを作成する時に、reference
をよく使うけど、「あれ、foreign_key: true
必要なんだっけ?」 「index
って勝手につくんだっけ?」 っていつもなるから、まとめておく。
前提
- mysql5.7.18 (DBが違うと挙動が違うことがあるので注意)
- rails5.1.6
まず試す
テーブルの作成から
rails g model test_model test_column:references
とすると、以下のファイルが生成される。
db/~~~create_test_models.rb
class CreateTestModels < ActiveRecord::Migration[5.1]
def change
create_table :test_models do |t|
t.references :test_column, foreign_key: true
t.timestamps
end
end
end
bundle exec rake db:migrate
で、、
db/schema.rb
ActiveRecord::Schema.define(version: 20180409130332) do
...
create_table "test_models", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.bigint "test_column_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["test_column_id"], name: "index_test_models_on_test_column_id"
end
...
add_foreign_key "test_models", "test_columns"
...
end
references
使ったらindex
は自動でつきますね、、
foreign_key
は指定してあげないとつかないみたい。
一応foreign_key: true
がない場合でもやってみよう。
db/~~~create_test_models.rb
class CreateTestModels < ActiveRecord::Migration[5.1]
def change
create_table :test_models do |t|
t.references :test_column, null: false
t.timestamps
end
end
end
bundle exec rake db:migrate
で、、
db/schema.rb
ActiveRecord::Schema.define(version: 20180409130332) do
...
create_table "test_models", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.bigint "test_column_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["test_column_id"], name: "index_test_models_on_test_column_id"
end
...
end
やはりforeign key制約はついてない。
add_reference
もやってみよう。
rails g migration AddAdditionalColumnToTestModels additional:references
↓
db/~~~add_additional_column_to_test_models.rb
class AddAdditionalColumnToTestModels < ActiveRecord::Migration[5.1]
def change
add_reference :test_models, :additional, foreign_key: true
end
end
同じ感じ。 foreing_key: true
がついているので、
db/schema.rb
ActiveRecord::Schema.define(version: 20180409130332) do
...
create_table "test_models", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.bigint "test_column_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "additional_id"
t.index ["additional_id"], name: "index_test_models_on_additional_id"
t.index ["test_column_id"], name: "index_test_models_on_test_column_id"
end
...
add_foreign_key "test_models", "additionals"
...
end
index
もforeign key
もついてる。
結論
t.reference
自体はindex
は貼ってくれるが、foreign_key制約までは面倒をみてくれない。だから、自分で書くときはforeign_key: true
を忘れずに。