【Rails】we're sorry, but something went wrongでハマった話(2)

こんにちは！スージーです！
ローカル環境では問題なかったのに本番環境で発生した`we're sorry, but something went wrong`の解決までを備忘録として

## we're sorry, but something went wrong
このエラーは本番環境でちょいちょい見るので`production.log`でエラーログを確認する

```terminal:ターミナル
[ec2-user@ip-~~]$ cd /var/www/app-name
[ec2-user@ip-~~]$ cd log
[ec2-user@ip-~~]$ cat production.log
D, [2019-11-18T07:06:44.834244 #5661] DEBUG -- : hogehoge~~
D, [2019-11-18T07:06:44.834597 #5661] DEBUG -- : hogehoge~~
・
・・
・・・
```
この時は`production.log`にエラーログが無かった

## デバックを考える

- `タイポ`→×
開発環境でもエラーが再現されているはず
-  `no method error`→×
開発環境でもエラーが再現されているはず
- `ルーティング`と`アクション`,`コントローラ`の記述がおかしい→×
開発環境でもエラーが再現されているはず
- エラー発生ページ`showアクション`の`:id`が本番環境にないのではないか？(同期が教えてくれた)

## 本番環境のMySQLにログインしてみる

同期の助言により、以前に本番環境下で`seedファイル`のデータが投入できなかった事を思い出す

```terminal:ターミナル
[ec2-user@ip-~app-name]$  mysql -u root -p
Enter password:
・
・・
mysql > use app-name_production;
・
・・
database changed
mysql > describe meals;
# <エラーが発生するテーブル>
mysql > show * form meals;
# <レコードを確認>
```

## mealsテーブル

| Column   | Type       | Options               |
| -------- | ---------- | --------------------- |
| name     | varchar    | null: false           |
| image    | text       |                       |
|food_stuff| text       |                       |
|cooking_time| integer  | null: false           |
|cooking_method| integer|                       |
|post_id   | integer    | null: false           |
|user_id   | integer    | null: false           |

## エラー箇所特定

`user_id:1`で投稿したはずなのに`mealsテーブル`の`user_idカラム`には`user_id:17`で保存されている...
開発環境では問題なく`user_id`が保存されているから道理でエラーが再現されないはずだ...

## 原因

この`user_id`はデプロイ後に追加したカラム
開発環境でマイグレーションファイルを作成した後に以下の手順でdb:migrateした

```terminal:ターミナル
[ec2-user@ip-~app-name]$ RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop
#<最新のDBにする為,一度drop>
[ec2-user@ip-~app-name]$ rake db:create RAILS_ENV=production
#<DBをcreateする>
[ec2-user@ip-~app-name]$ rake db:migrate RAILS_ENV=production
#<migrateする>
[ec2-user@ip-~app-name]$ cd current
#<currentディレクトリ下へ>
[ec2-user@ip-~app-name]$ rake db:seed RAILS_ENV=production
・
・・
・・・
Mysql2::Error: Field 'user_id' doesn't have a default value
```

上記エラーが最初出た時に`user_id`カラムをMySQLにログインしてカラムを新規で作成し突っ込んでいた

```terminal:ターミナル
database changed
mysql > ALTER TABLE meals ADD user_id int;
mysql > exit
[ec2-user@ip-~app-name]$ cd current
[ec2-user@ip-~app-name]$ rake db:seed RAILS_ENV=production
・
・・
・・・
Mysql2::Error: Field 'user_id' doesn't have a default value
```
またエラーが出ている...アプリを動かして投稿してみると新規投稿はできていたので、その時は一旦保留にしていたが、やはりここが今回のエラーの原因であるのは間違いなさそう

## 解決方法

なぜ最新のマイグレーションファイルが本番環境に反映されないのか

>参考
【Rails】本番環境デプロイでよく使うコマンド集！AWS/unicorn/nginx/Capistrano使用
https://qiita.com/15grmr/items/7ad36caa82a0fa27c4bd

むむむ...db:migrateの手順が間違っていた...無理矢理に本番環境のDB構造を変えて正しく`user_id`が保存されていないのが原因であれば正しくマイグレーションすればエラーは解決するはず。そうすればdb:seedでデータが投入されるはずである

```terminal:ターミナル
[ec2-user@ip-~app-name]$ RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop
[ec2-user@ip-~app-name]$ rake db:create RAILS_ENV=production
# ここで一度自動デプロイをかけて、db:migrateに当たる操作を完了
# ローカルにて
app-name $ bundle exec cap production deploy
# 無事作成されたら、再度EC２のcurrentディレクトリでseedを反映させる
[ec2-user@ip-~app-name current]$ rake db:seed RAILS_ENV=production
・
・・
・・・
[ec2-user@ip-~app-name current]$
```
無事にseedファイルが本番環境に投下され`we're sorry, but something went wrong`のエラーは解決

## まとめ

今回、個人アプリで初めてデプロイ後のDB構造を変更・追加を行った。EC2内で`db:create→db:migrate`までしてから自動デプロイしても最新のマイグレーションファイルが本番環境へ反映されない事が原因だった。EC2内では古いDBを`drop`し`create`する所までを行い、capistranoを使った自動デプロイで最新マイグレーションをファイルの読み込み`migrate`する

今回のエラーはデプロイの手順の間違えで発生したものだったが、MySQLを触っているとRailsではマイグレーションファイルでバージョン管理してくれるし、ORMのお陰で生SQLを触る機会もほとんどないのでDB関連の知識が無くても動くアプリケーションが作れる。非常に便利だが、SQLの勉強は絶対にした方が良いと感じたエラーだった