開発環境
・Mac OS Big Sur 11.2
・Ruby 2.6.5
・Rails 6.0.0
エラーの状況
アイディアを管理するためのAPIを、railsを用いて作成。
ideasテーブル、categoriesテーブルを作成し、rails db:migrateコマンドを実行した結果、以下のようなエラーが出ました。
== 20210411003522 CreateIdeas: migrating ======================================
-- create_table(:ideas)
rails aborted!
StandardError: An error has occurred, all later migrations canceled:
Mysql2::Error: Table 'category_app_development.categories' doesn't exist
エラー内容を見ると、"Mysql2::Error: Table 'category_app_development.categories' doesn't exist"
とあり、categoriesテーブルが存在しない、と指摘されています。
ideasテーブル、categoriesテーブルをそれぞれ見てみます。
class CreateCategories < ActiveRecord::Migration[6.0]
def change
create_table :categories do |t|
t.string :name, null: false
t.timestamps
end
end
end
class CreateIdeas < ActiveRecord::Migration[6.0]
def change
create_table :ideas do |t|
t.references :category, foreign_key: true
t.text :body, null: false
t.timestamps
end
end
end
ideasテーブルに、"t.references :category, foreign_key: true" とあるように、ideasテーブルは外部キーとしてcategoriesテーブルを参照しています。categoriesテーブルが親テーブル、ideasテーブルが子テーブルという関係です。
外部キー制約を設定する場合、外部キーの対応するデータが必ず存在しなくてはいけません。
外部キー制約とは、「他のテーブルのデータに参照(依存)するようにカラムに付ける制約」だからです。
ところが、今回のやり方だとcategoriesテーブルとideasテーブルを同時にmigrateしてしまい、本来なら先に作成されているべき親テーブルであるcategoriesテーブルが存在しない、といったエラーが出ていたのです。
解決方法
rails d model ideaコマンドで、ideaモデルとテーブルを一旦削除。
その後、rails db:migrateを実行し、まずはcategoriesテーブルを作成します。
そして、ideasモデルとテーブルを再度作成し、rails db:migrateを実行するとideasテーブルも無事に作成できました。
まとめ
外部キー制約は、親テーブルに存在しないデータを子テーブルに登録させないためのツールですので、テーブルを作成する時にも、まずは親テーブルを作成してから子テーブルの作成をするように気をつけたいです。