概要
初学者が勉強のため、rails + mysqlで記事投稿アプリを作成中。
article(記事)テーブルに紐づくuserカラムに外部キー制約をつけ忘れていることに気付き、
新たにマイグレーションファイルを作成し、foreign_key: trueを追加した。
capistranoによるデプロイで、migrateの段階でエラーが発生した。
解決方法
本番環境において
$ RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop`
$ rails db:create RAILS_ENV=production
$ rails db:migrate RAILS_ENV=production
することで、無事にデプロイができました。
詳細とエラー解決時の思考
デプロイ時のエラーメッセージ
deploy:migrating
01 $HOME/.rbenv/bin/rbenv exec bundle exec rake db:migrate
01 == 20210128023243 AddUserToArticles: migrating ================================
01 -- add_reference(:articles, :user, {:null=>false, :foreign_key=>true})
01 rake aborted!
01 StandardError: An error has occurred, all later migrations canceled:
01
01 Mysql2::Error: Duplicate column name 'user_id'
むむむ、どうやら外部キー制約をつけたmigrationファイルが悪さをしているようだ、、、。
初めは構文エラーを疑いましたが、ローカル環境では問題なく記事投稿できていることからそれはなさそうだと判断。
本番環境のみでエラーが起きているので、ローカル環境との差異である、既に登録されているデータが問題かな、と思いました。
エラーを見るとDuplicate(複製) coiumn name!とあるし、、、
本番環境に登録されているのはテストデータだけだったので、一旦削除することにしました。
ターミナルから直接Mysqlを操作する経験があまりなかったので、調べながらチマチマ、、
#datebase名を指定する
mysql> use datebase名;
#とりあえずデータを確認
mysql> select * from articles;
#削除して問題ないので全て削除するぞ
mysql> delete from articles;
再度capistranoでデプロイ!しようとしたが、同じエラー、、、
userのデータも削除しないとかぁ
上記と同様の手順で
mysql> delete from users;
よし!デプロイ!!したけど、やはりエラー。。。
Duplicate column name user_idについてもう一度考えてみる。
既にuser_idというカラムがあるところにカラムを追加しようとしている、、、?
データだけでなく、テーブル設計を修正しないといけないことに気づく。
その後、解決方法の手順を踏んで、無事に解決できました!!
学び
単純でありがちっぽいエラーでしたが、自分にはたくさん学びがあったように感じます。
-
テーブル設計が大事
そもそも序盤のテーブルを作成していく段階で外部キー制約をつけていたら起こらなかったエラーな訳で、、、。テーブル設計をしっかり行った上で、作成に入りましょう。
-
小さなステップで実装&確認
実はこの外部キー制約を修正したのは2週間ほど前。ブランチもマージしていたが、ローカルで動作することを確認してデプロイはしていなかった。昨日、別のブランチをマージしたのでデプロイしたところエラーが発覚。
今回は2つのブランチで作業内容が全然違ったため、エラーの原因が明確だったが、類似するような作業のブランチだった場合、どちらの作業が原因なのか判断が難しくなるリスクがある。せっかくcapistrano使ってるんだから、横着せずに一つの実装で1回デプロイして、必ず動作確認!(当たり前ですが)
-
ターミナルでのMySQLの操作
ローカルだとGUIのツールを使ってDBの中身を確認してたので、CUIでDBを操作する機会になりました。特にRailsだとActiveRecordでSQLを書くこともないので、一度勉強したはずなのにSELECT * FROM articles;も検索しないと書けなかった、、、。今後はCUIで確認、操作していきます!