Rails で元に戻せないマイグレーションを書くときの作法: ActiveRecord::IrreversibleMigration
ActiveRecord のマイグレーションは,その中に up
メソッドと down
メソッドを書くことにより,データベースのスキーマを更新したり,変更を元に戻したりすることができ便利です.Rails 3.1 からは up
, down
を change
メソッドにまとめて書くことができるようになりました.
しかし,すべてが元に戻せるマイグレーションかというと,そうではないことがあります.たとえば,
この図のように,integer だった vendor_code
カラムを string に変更する場合,変更後のカラムに文字列を入れてしまうとマイグレーションで元に戻すことができません.文字列を数値に変換することができず,データが失われてしまうからです.このように,元に戻らないマイグレーションを書くときには,down
メソッドで ActiveRecord::IrreversibleMigration
を raise
するようにします.
すなわち,マイグレーションは,
class ChangeVendorCodeToString < ActiveRecord::Migration def up change_column :items, :vendor_code, :string, null: false end def down raise ActiveRecord::IrreversibleMigration end end
のようになります.こうしておくと,不用意な rollback でデータが破壊されるという悲劇がなくなります↓
% rake db:migrate == ChangeVendorCodeToString: migrating ======================================= -- change_column(:items, :vendor_code, :string, {:null=>false}) -> 0.0295s == ChangeVendorCodeToString: migrated (0.0296s) ============================== % rake db:rollback == ChangeVendorCodeToString: reverting ======================================= rake aborted! An error has occurred, this and all later migrations canceled: ActiveRecord::IrreversibleMigration Tasks: TOP => db:rollback (See full trace by running task with --trace)
この記事を書いたときの Rails のバージョン
3.1.1