はじめに
今回は久しぶりのErrorが起こったので何が原因だったのか、そしてどのような解決方法があり、実際どうしたのか、についての記事になります。マイグレーション実行する際について学んだことをアウトプットしたいと思います。
環境
- Windows, WSL
- Docker
- Ruby 3.2.3
- Rails 7.1.3
エラー内容
# rails db:migrate
== 20240830014857 CreatePosts: migrating ======================================
-- create_table(:posts)
bin/rails aborted!
StandardError: An error has occurred, this and all later migrations canceled: (StandardError)
PG::UndefinedTable: ERROR: relation "prefectures" does not exist
/myapp/db/migrate/20240830014857_create_posts.rb:3:in `change'
Caused by:
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "prefectures" does not exist (ActiveRecord::StatementInvalid)
/myapp/db/migrate/20240830014857_create_posts.rb:3:in `change'
Caused by:
PG::UndefinedTable: ERROR: relation "prefectures" does not exist (PG::UndefinedTable)
/myapp/db/migrate/20240830014857_create_posts.rb:3:in `change'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
・上記エラー文から、マイグレーションが正常に完了しなかったことを示しています
・エラーメッセージに「relation prefectures
does not exist」とあるように、prefectures
テーブルが存在しないため、posts
テーブルの作成時にエラーが発生しています。
このエラーが起きた原因
posts
テーブルのマイグレーションファイルで、prefecture_id
という外部キーを設定しているため、prefectures
テーブルが存在する必要があります。しかし、prefectures
テーブルがまだ作成されていないためにエラーが発生しました。
Prefecture
, Station
, Line
,Post
テーブルなど、すべてのマイグレーションファイルとモデルファイルへの編集を一度に行ってからまとめてマイグレーションを実行しようとしたことが原因です(タイムスタンプの順番という概念が皆無)
対処法(提案されたもの)
-
関連モデルのマイグレーションを先に実行:
-
prefectures
,stations
,lines
, およびfavorites
テーブルを作成するマイグレーションファイルを先に実行する必要があります。これらのテーブルが存在しないと、posts
テーブルの作成時に参照できず、エラーになります。
-
-
順序を確認:
- マイグレーションファイルの実行順序を確認し、まず
Prefecture
,Station
,Line
,User
テーブルを作成してからPost
テーブルを作成するようにします。
- マイグレーションファイルの実行順序を確認し、まず
提案された対処法に対しすべて作成済みなので時すでに遅し
・すでにすべてのファイル等は作成していたのでその旨を伝えたところ次の対処法が提案
対処法2(新たな提案)
1. マイグレーションのリセット (オプション)
まず、すべてのマイグレーションをリセットして、最初から再実行する方法があります。この方法はテスト環境や開発環境で推奨されますが、実際のデータがある本番環境では注意が必要です。
rails db:migrate:reset
このコマンドは、すべてのデータベースをリセットしてから、すべてのマイグレーションを再実行します。
2. マイグレーションを個別に実行
もしリセットが適さない場合は、問題が発生している順にマイグレーションを個別に実行していくことができます。
個別マイグレーションの手順
-
Prefecture
,Station
,Line
テーブルを作成:
まず、prefectures
,stations
,lines
,users
テーブルを作成するマイグレーションファイルを手動で実行します。例えば、CreatePrefectures
マイグレーションがdb/migrate/20240830014857_create_prefectures.rb
にあるとします。rails db:migrate:up VERSION=20240830014857
この手順を、
stations
,lines
,users
の各マイグレーションファイルについても繰り返します。 -
Post
テーブルの作成:
関連するテーブルがすべて作成された後に、Post
テーブルを作成するマイグレーションを実行します。rails db:migrate:up VERSION=20240830014858
-
残りのマイグレーションを実行:
他のマイグレーションファイルが残っている場合は、rails db:migrate
コマンドを使って残りを一括で実行します。rails db:migrate
実際にしたこと
都道府県
rails db:migrate:up VERSION=20240830025850
路線
rails db:migrate:up VERSION=20240830030833
駅
rails db:migrate:up VERSION=20240830044413
最後にポスト
rails db:migrate:up VERSION=20240830014857
・リセットするには正直これまで頑張って作ったのに、という思いが強かったので一つずつ実行することに。
・Versionの入力間違いには注意!!
おまけ:マイグレーションの順番を確認する
マイグレーションが正しい順序で実行されるように、ファイルの名前とタイムスタンプを確認が必要。db/migrate/
ディレクトリ内のファイルはタイムスタンプ順に実行されるためです!!
ついでに、マイグレーションファイルのタイムスタンプは、ファイル名の先頭部分に含まれています。Railsでは、マイグレーションファイル名が次の形式で命名されます。
YYYYMMDDHHMMSS_create_table_name.rb
ここで、YYYYMMDDHHMMSS
の部分がタイムスタンプになります!このタイムスタンプにより、マイグレーションが実行される順序が決まります。
例えば、以下のようなファイルがあるとします。
20240830014857_create_prefectures.rb
20240830014858_create_stations.rb
20240830014859_create_lines.rb
20240830014860_create_posts.rb
この場合、ファイル名のタイムスタンプ部分 (20240830014857
, 20240830014858
, など) を見れば、どの順番で実行されるかがわかります。Railsは、このタイムスタンプの順序でマイグレーションを自動的に実行します。
さいごに
タイムスタンプを確認したい場合は、db/migrate/
ディレクトリ内のファイル名を見ることがいいということ、タイムスタンプ順に実行されること、順番の概念がないとこの先ひどい間違いを起こしてしまうかもしれないという事。を学びました。
今回の記事が何か参考になれば幸いです。