Railsを使うときに、マイグレーションは便利ですが、戻すときのことまで考えて実装していますでしょうか。
bin/rails db:rollback
bin/rails db:migrate
でマイグレーションを実行できますが、逆にbin/rails db:rollback
で戻すこともできます。ただし、マイグレーションが戻ることを前提にしている必要があります。
考えなくて良いパターン
create_table
やadd_column
など追加系のメソッドをchange
に書いていた場合、逆向きは「追加したものを削除する」ことが明らかですので、自分で書かなくても対応してくれます。
戻し方を書けば対応してくれるパターン
drop_table
やremove_column
を行う場合、ただ削除する内容を書くだけでは、戻し方がわかりません。そこで、これらのメソッドはcreate_table
やadd_column
と同様に元の定義を書けるようになっています。ロールバック時にはそれが使われます。
戻さない・戻せないパターン
たとえば、NULL
の列をNOT NULL
に変えるとか、utf8
だった列をutf8mb4
に入れ替えるとか、int
の列をstring
に変えるとか、値域を広げる方向にマイグレーションをかけた場合、元に戻そうにも広がった後のデータが入らないことがあるので、戻しようがありません。
このような場合はup
だけ書いて、down
はraise ActiveRecord::IrreversibleMigration
とすることで、「戻せない」ことをコードで明示できます。
また、現実問題としてデプロイ後にマイグレーションをロールバックするような運用は通常行いませんので、ある程度以上複雑なマイグレーションを書いた場合に、戻す方まで厳密に書かずにraise ActiveRecord::IrreversibleMigration
で済ます、という手段も、状況によってはありかもしれません。
戻す側が不要になる場合
時には、戻す側で何もしなくていいことがあります。たとえば、「あるカラムに空文字列とNULL
が混在しているので、全てを一方に揃える」というようなマイグレーションを立てたとします。これのdown
側は、特に何もしなくても元のデータと整合するので、放置して構いません。このような場合、
def down
# 戻す側で何もしなくていい理由
end
のように、コメントで間違いではないことを明記しておきましょう。