個人開発中のアプリケーションのデータベースの型を変更しようとしたら、herokuの本番環境のみ、エラーが出てしまいました。
この時のエラーの解決方法を解説します。
環境
- 言語:Ruby 2.5.3
- フレームワーク:Rails 5.2.3
- データベース(development/test):Mysql
- データベース(production):Postgresql
- デプロイ:Heroku
調べていながら分かったのですが、development環境とproduction環境で異なるデータベースを利用するケースは少ないのですね。
プログラミングスクールでは、環境構築の学習コストを抑えるため、このように教わったのですが、いずれはデータベースを統一しようと思います。
マイグレーション実行とエラー
下記マイグレーションを実行したところ、
class ChangeDataRateToPost < ActiveRecord::Migration[5.2]
def change
add_column :posts, :new_rate, :float
end
end
rails db:migrate
→ OK
heroku run rails db:migrate
→ エラー
PG::DatatypeMismatch: ERROR: column "rate" cannot be cast automatically to type double precision
HINT: You might need to specify "USING rate::double precision".
Postgresqlはデータの型の変更がうまくいきませんでした。
問題の切り分け
1.マイグレーション内容の変更
エラー内容から、データ型を変更するときはUSING
というオプションをつけて型を変更する必要があるようです。
2.環境ごとに異なるマイグレーションの実行
development環境のマイグレーションは上手く実行できているので、USING
のオプションをつけたマイグレーションの実行はproduction環境
のみで行う必要があります。
マイグレーションやり直し
PostgreSQL vs. Rails migration: How to change columns from string to integerを参考に
# integer型への変更(変更前の型は記載しなくて良い)
change_column :table_name, :column_name, 'integer USING CAST(column_name AS integer)'
下記のマイグレーションを変更しました。
class ChangeDataRateToPost < ActiveRecord::Migration[5.2]
def up
# 環境ごとにマイグレーションを分ける
if Rails.env.development? || Rails.env.test?
change_column :posts, :rate, :float
else Rails.env.production?
# 本番環境はusingオプションを追加
change_column :posts, :rate, 'float USING CAST(rate AS float)'
end
end
def down
change_column :posts, :rate, :string
end
rails db:migrate
→ OK
heroku run rails db:migrate
→ エラー
*herokuの環境は事前に確認できないため、リスクの高い方法です。staging環境を用意してから実行するのが望ましいようです。
今後の課題
1.development/test/production/全ての環境で同一のデータベースを利用する。
2.staging(ステージング環境)を用意して、production環境に手を加えずに挙動確認が可能な環境を構築する。
最後に
2018年12月にプログラミングを始め、プロテインの口コミ共有サービスを開発しています。一目見ていただけたら嬉しいです。
「SuppleBox - プロテイン特化型口コミ共有サービス -」
URL: https://supplebox.tokyo
GitHub: https://github.com/yuki0920/supplebox