Tatehitoの技術メモ

ソフトウェアエンジニアです。いろいろ書きます。

【Rails】開発環境をSQLite、本番環境をPostgreSQLで構築すると後々面倒なことになるかも?

RailsのデフォルトDBはSQLiteです。一方、アプリケーションを簡単にデプロイできることで人気のPaaSであるHerokuのデフォルトDBはPostgreSQLです。

Railsでは環境ごとに異なるDBを利用している場合でも、基本的に問題なく動作します。かの有名なRailsチュートリアルでも、開発環境はSQLite、本番環境(Heroku)はPostgreSQLを使って進んでいきます。*1

これまでDBの差異によって特に困ったことがなかったので、開発環境はSQLite、HerokuはPostgreSQLという構成にしていました。が、先日ついに困ったことが起きました。

migrationファイルの構文が両立できない

Railsで既存カラムのデータ型を変更する場合、一般的には以下のmigrationファイルを用意し、rails db:migrateします。

def change
  change_column :users, :age, :integer
end

このmigrationファイルはSQLiteでは問題なく実行できます。しかし、PostgreSQLではPG::DatatypeMismatch〜というエラーになってしまいます。

PostgreSQLでは、以下のように書くとmigrationを実行できます。

def change
  change_column :users, :age, 'integer USING CAST(age AS integer)'
end

しかし、これだと今度はSQLiteでエラーが起きてしまいます。つまり、SQLiteとPostgreSQLで互換性のある書き方がないということになります。

特に理由がない限り使用するDBは揃えておくべき

Rails.env.development?Rails.env.production?を使って環境ごとに実行するchange_columnを切り替えることはできますが、今回の事象以外にもDBの違いは少なからずあると思いますし、そもそもDBを統一しておけば発生しない問題です。

特に理由がなければ全ての環境でDBを統一すべきだと再認識しました。

幸いこの事象に遭遇したアプリケーションは制作中で非公開だったので、どちらの環境もMySQLに統一することで問題を回避しました。公開済みのアプリの場合、簡単にはDBを変更できないので、早い段階で統一するのが良さそうです!

*1:開発環境にPostgreSQLをインストールする演習があるが、難しければ飛ばして良いとなっている