Rails でマイグレーションファイルをまとめる Squasher gem を使う

Squasher gem

こちらの gem です。Rails におけるマイグレーションファイルをまとめるための gem です。

インストールの方法

この gem を使うためにはもちろんインストールをする必要があります。公式ドキュメント では Rails のGemfile に書く方法が紹介されています。

しかしながら、私は $ gem install squasher によってユーザーグローバルにインストールしたほうがいいと思います。なぜなら、この gem を使う頻度を考えると、プロジェクトの共通の Gemfile に書く必要性が薄いからです。依存関係により bundle install が失敗し*1、それの原因を探るために時間を費やすくらいならば初めから Gemfile に書かないほうが良いと思っています。

単に Gemfile はシンプルに必要最小限に保ちたいというのも理由です。

使い方

インストールしたらさっそく使ってみます。以下のコマンドの説明では、$ gem install squasher を行ったものとします。Gemfile に書いて bundle install をした場合は、$ squasher の部分を $ bundle exec squasher と置き換えてください。

0. 環境変数をコマンド実行時に指定しつつ実行する

$ gem install squasher でインストールして Squasher を使う場合は、環境変数をコマンド実行時に指定します。dotenv-railse は用いられないため、以下のように指定する必要があります。direnv を使うのもいいでしょう。

$ POSTGRES_USER=foobar squasher --help

以後のコマンドの表記では、この環境変数を記述する部分は省略します。

1. 年月日を指定してマイグレーションファイルをまとめる

squasher コマンドの引数に 年/月/日 を指定することで「指定年月日より以前の」マイグレーションファイルがまとまります。例えば、2020/03 と指定子た場合は、2020年2月を含む、それ以前のマイグレーションファイルがまとまります。

2. マイグレーションのバージョンを -m オプションを用いて指定する

任意のマイグレーションファイルの継承元である ActiveRecord::Migration のバージョン番号を、squasher コマンドの -m オプションで指定します。

例えば、任意のマイグレーションファイルの冒頭に以下のように書いてあったとします。

class CreateHogeTable < ActiveRecord::Migration[6.0]

この場合、squasher コマンドの -m オプションには以下のように書きます。

$ squasher -m 6.0

3. コマンドの最終段階で出てくる 2つ の質問にどう答えるか

squasher コマンド実行すると、最後に次のような質問が表示されます。

Squasher's created the `squasher` database for its needs.
It might be useful to keep it if any of your deleted migrations inserts data or
you squash migrations in a few steps (look at -r option).
Keep it (yes / no)?
yes
Do you want to clean your database from the old schema migration records(yes/no)?
no

Keep it (yes / no)? の方は、yes と答えると squasher という名称でデータベースを作ってくれ、そこにコマンド実行前のデータベースのスキーマを構築しておいてくれます。バックアップ的なものと考えてよいでしょう。

Do you want to clean your database from the old schema migration records(yes/no)? の方は、yes と答えると、db:migrate:reset を行います。つまり、既存のデータベースを drop して、db:migrate をやり直します。レコードが消えてしまうので注意です。

補足

範囲を指定してまとめることはできません。つまり「ある地点より以前のファイルをまとめる」ことができるのみです。5年分のマイグレーションファイルがあるプロダクトにおいて、たとえば1年毎に1つのファイルにまとめて合計5ファイルにする、ということはできません*2

このあたりは $ git rebase で起きることがあるコンフリクトの嵐を考えれば、機能があることによる弊害は小さくないと思いますので、しょうがないかなと考えています。

*1:おそらく無いでしょうが

*2:……のはずです

Powered by はてなブログ