はじめに
Rails開発において、1回目のデプロイは成功しても、2回目で「DBのカラム名変更」や「マイグレーションファイルの削除」が加わると、一気に難易度が跳ね上がります。 今回、「ローカルでは動くのに本番(Render)で壊れる」という絶望的な状況から、設計図(README)を軸に全てを同期させて解決したプロセスを共有します。
- 発生した問題:負の連鎖
商品出品機能の実装中、カラム名を description から info に変更したことをきっかけに、以下のエラーが連鎖しました。
Renderデプロイ失敗: ActiveRecord::PendingMigrationError が発生。
500エラー: デプロイ成功後も、保存ボタンを押すと内部サーバーエラーで出品できない。
JSの沈黙: 価格を入力しても手数料の自動計算が全く動かない。
定数エラー: uninitialized constant SalesStatus(ActiveHashが見つからない)。
- 徹底解剖:なぜ「不整合」が起きたのか?
① マイグレーションの「物理削除」という禁じ手
不要になったファイルを、db:rollback せずに削除してしまいました。 RailsはDB内の schema_migrations テーブルに実行済みの履歴を持っていますが、実体のファイルが消えたことで、「記録はあるのに設計図がない」という矛盾が生じ、Renderが起動を拒否しました。
② 「ローカルLGTM」の罠
ローカルDBには、以前の試行錯誤で作った「古いカラム」がたまたま残っていました。 そのため、コードが不完全でもローカルでは動いてしまい、「真っさらな環境(本番)」で初めてバグが表面化するという事態に陥りました。
③ JavaScript(importmap)の仕様
本番環境でのみJSが動かなかったのは、アセットパイプラインの記述ミスでした。
誤: import "./item_price"(相対パス指定)
正: import "item_price"(名称指定) Rails 7の importmap-rails では、ピン留めした名称を正しく指定しないと本番環境でファイルを認識できません。
- 解決策:設計図(README)を「絶対正義」にする
メンターさんのアドバイスを元に、バラバラになった情報をREADMEに合わせる形で完全同期させました。
STEP 1:DBの強制初期化
履歴の矛盾を解消するため、環境を一度クリーンにしました。
Bash
ローカルDBを更地にして設計図通りに再構築
bin/rails db:migrate:reset
STEP 2:全レイヤーの名称同期
READMEを唯一の正実(Single Source of Truth)とし、すべての名称を1ミリの狂いもなく統一しました。
DB: info, sales_status_id ...
Model: validates :info, belongs_to_active_hash :sales_status
Controller: item_params の permit 項目
ActiveHash: クラス名(SalesStatus)とファイル名(sales_status.rb)を完全一致
STEP 3:JavaScriptセレクタの固定
DBのカラム名変更に左右されないよう、View側で id を明示的に指定し、フロントとバックを疎結合にしました。
コード スニペット
<%# 命名変更に強いフロントエンド実装 %>
<%= f.text_field :price, id: "item-price" %>
4. この経験から得た教訓
「自分のマシンで動く」は100点ではない: 本番という「真っさらな環境」で動いてこそプロ。
マイグレーションは手順が命: ファイルを消す前には必ずロールバックしてDBの履歴を消す。
命名は「契約」である: 自分の好みで名前を付けず、設計図(README)に忠実になる。
JSとの結合を意識する: バックエンドの名称変更は、必ずフロントエンド(ID名)に波及する。
おわりに
エラーは「Railsの仕組み」を深く知るための最高の教材でした。一見遠回りに見える「DBリセット」や「全ファイルの見直し」が、結局は一番の近道であることを痛感しました。