LoginSignup
14
12

More than 3 years have passed since last update.

RailsでHerokuにデプロイしたときに一部ページだけ500エラーとなるとき

Last updated at Posted at 2020-06-23

マイグレーションファイルは慎重に作成し、ミスったらやり直すくらいの覚悟じゃないとHerokuにpushしてheroku run rails db:migrateしたときに沼にハマるよという話。

発生している問題

ローカル環境ではキチンと動くのに、(SQLite->Postgresへの対応などの基本的な設定を済ませてから)Herokuにデプロイするも、一部のページだけが500(Internal Server Error)となる。フロントでは「We're sorry, but something went wrong.」なので、404の「The page you were looking for doesn't exist.」とは違って内部的なエラーが発生している。
スクリーンショット 2020-06-23 21.58.17.png

heroku logs --tailでログを見ても以下の500エラーと書かれただけで何が原因か全然分からないかった。

2020-06-23T09:27:34.223359+00:00 app[web.1]: [8ee3a40d-5258-46f4-8742-48c47f28b01f]   Category Load (1.2ms)  SELECT "categories".* FROM "categories"
2020-06-23T09:27:34.474847+00:00 heroku[router]: at=info method=GET path="/categories/1/show" host=my-app.herokuapp.com request_id=8ee3a40d-5258-46f4-8742-48c47f28b01f fwd="27.81.17.54" dyno=web.1 connect=1ms service=263ms status=500 bytes=1827 protocol=https

結論

汚いマイグレーションファイルを残したままpushしてheroku run rails db:migrateしていないか疑え!

以下の記事の【1】と同じだった。
https://qiita.com/kaorioka09jm/items/9167ba77d1edf7addac2

ローカル開発中にDB作りを試行錯誤したことが原因

Herokuにデプロイした全ページが500とかならheroku run rails db:migrateしてないなど他の理由もあるが、一部のページだけ表示されない場合はDBのマイグレーションが上手くいっていない場合が多いようだ。

結局、ローカルのマイグレーションファイルを削除したり、作り直したりしても、一度Herokuにpushしてしまったマイグレーションファイルがあると、データベースをResetしてもDestroyしても、そこからheroku run rails db:migrateしてもデータベースは綺麗にならない。

そのため筆者の場合はHerokuからアプリを削除して再度pushし直す羽目になった。

マイグレーションファイルの注意点

  • マイグレーションファイルは一度しかrails db:migrateできない
  • 生成されるschema.rbを直接編集しちゃダメ(と思われる)
  • テーブルの削除なども都度マイグレーションファイルを作ってやること

そのため以下のようなマイグレーションファイルの生成は慎重に行う必要がある。もし間違ってカンマを入れたり本来integerのデータ型を間違ってtextに指定してしまったなどだけで、変なマイグレーションファイルが生成される。

// 例
rails g migration CreatePostCategoryRelations post_id:integer category_id:integer
// 間にカンマを入れたり、コロンの位置が違ったり、integerの綴りが違ったりと間違えがち

それを挽回するために別のマイグレーションファイルを作って‥なんてやってローカルでDBをぐちゃぐちゃ構築しても、それをpushした後にheroku run rails db:migrateを実行すると過去のマイグレーションファイルを順に実行するのでおかしくなる。

今回はPosticoの使用により、DBの中のあるテーブルのcategory_idカラムがStringになっていたことに気付けたので、Heroku側のDB生成が上手くいってないことに気付けた。

DBがおかしいと気付くには、rails db:migrateした際のログをめんどうでもちゃんと読んで確認するのも役立つと思う。

  • キチンと標準のテーブル+マイグレーションファイルで指定したテーブルが作成されているか?
  • 各テーブルのカラムのデータ型は正しいか?

テーブルの削除

Heroku上に正しいマイグレーションファイルをpushするには、まずローカルのマイグレーションファイルを綺麗にする必要がある。しかし、間違った記述のあるマイグレーションファイルを削除し、正しいマイグレーションファイルを作成してrails db:migrateしても、以下のように怒られて上書きはできない。

rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: table "post_category_relations" already exists

そのためテーブルの削除用のマイグレーションファイルを作成してrails db:migrateし、再度新たなテーブル作成用のマイグレーションファイルを作成してrails db:migrateする必要がある。

$ rails generate migration RemoveMyTable
20200623XXXX_remove_my_table.rb
class RemoveMyTable < ActiveRecord::Migration[6.0]
  def change
    drop_table :my_table
  end
end

その後、テーブルの削除などに使った余分なマイグレーションファイルを削除する。こうして綺麗なマイグレーションファイルだけが残ったので、これをまっさらなHerokuにpushしてからheroku run rails db:migrateをしてやると綺麗なデータベースができる。

考えたこと

SQLiteとPostgreSQLの互換性の問題ではないか

Herokuでは SQLite が使えないので、production環境だけ PostgreSQL を使用するのはHerokuで最初につまづくポイントだが、これの変更によって使えないメソッドがあるのではと考えた。

が、そんなことはなく、そもそもマイグレーションファイルとはSQLを書かずに、かつ言語の種類(SQLiteかPostgreSQLか等)によらずにDBを操作するためのものである。

今回はControllerの以下のincludeswhereがPostgreSQLでは使えないのでは、といった馬鹿な勘違いをしてしまった‥orz.

categories_controller.rb
def show
  @posts = Post.includes(:categories).where(post_category_relations: { category_id: @category })
end

※Gemのpgloaderを使うなどの記事を見つけたが、それはMySQLのデータをPostgreSQLのデータに移行するものであって、メソッドを変換とかではない。

push後のWarningされてる部分に問題があるのではないか

pushした後に以下のWarningが出るが今回は無関係。またこれらは、どれも特別な使い方をしない限りは、初心者は無視していい警告だ。

remote: ###### WARNING:
remote:        You set your `config.assets.compile = true` in production.
remote:        You set your `config.active_storage.service` to :local in production.
remote:        We detected that some binary dependencies required to
remote:        No Procfile detected, using the default web server.

マイグレーションファイルの理解を深めるのに役立ちそうな記事

そもそもマイグレーションとは何なのか👇
https://qiita.com/sobameshi0901/items/f5823fec20e2dd78d9c4

ロールバックという手法もあるらしい👇
https://qiita.com/params_bird/items/3d503b5c9f8097df147a

14
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
12