Railsでmigrationを作成する時、changeメソッドだけが定義されていたり、upとdownメソッドの2つが定義されている時があります。
class AddColumnHoge < ActiveRecord::Migration def change end end
class ChangeColumnHoge < ActiveRecord::Migration def up end def down end end
こんな風に、migrationファイルを作成した時の名前で、生成されるclassのひな形が違います。
up/downについて
upとdownメソッドは、migrateを実行した時の処理と、rollbackした時の処理を定義します。
upで変更したものは、downで元に戻るようにしておかないと、正しくrollbackできません。
class ChangeColumnHoge < ActiveRecord::Migration def up add_column :hoge, :fuga, :string end def down remove_column :hoge, :fuga end end
migrateを実行するとfugaカラムが追加され、rollbackするとfugaカラムが削除されます。
changeについて
changeメソッドは、migrateを実行した時の処理を定義します。
up/downと違うところは、rollback時の処理を勝手に反転して実行してくれるところです。
ですので、changeメソッドはrollback時の処理を書く必要はありません。
class AddColumnHoge < ActiveRecord::Migration def change add_column :hoge, :fuga, :string end end
これだけで、先ほどのup/downで挙げた例と同じ挙動になります。
rollback時はadd_columnを反転させて勝手にremove_columnが実行されます。
じゃあ全部changeでいいじゃん
と思いきや、changeだけでは成り立たないケースもあります。
class removeColumnHoge < ActiveRecord::Migration def change remove_column :hoge, :fuga end end
これは、migrate実行時はカラムを削除するだけなので、問題なく実行できます。
しかし、rollback実行時は失敗します。
rollback時、fugaカラムの情報はどこにも書いていないからです。
型が文字列なのか数値なのかもわからないので、カラムを作成することが出来ません。
なので、こういうケースはup/downを使います。
class removeColumnHoge < ActiveRecord::Migration def up remove_column :hoge, :fuga end def down add_column :hoge, :fuga, :string end end
downにfugaの定義をしっかりとしてあげることで、rollbackも正しく実行できます。
さらに上をいくRailsのよしなに力
つまり、migrationを生成する時の名前を見て、
- 「remove***」だったら多分反転できないからup/downケースにしとくねー
- 「add***」だったら消すだけだからchangeに任せてよ!
みたいなことをRailsがよしなにしてくれていたから、 名前によって生成されるClassのひな形が違うんですね。