Railsのマイグレーションファイルの記載方法として、
changeを使った方法と、up & downを使った方法があります。
それぞれの違いについては、他のネット記事でも紹介がありますが、
どういう場合に、どっちを使ったらいいねんというのを記載したいなと思います。
まずは、changeとup & down の記載方法について、おさらいがてら軽く記載します。
change での書き方
Userテーブルにstring型の存detailカラムを追加したいとき…
class AddDetailToUser < ActiveRecord::Migration
def change
add_column :users, :detail, :string
end
end
up & down での書き方
change
の時と同様に、Userテーブルにstring型のdetailカラムを追加したいとき…
class AddDetailToUser < ActiveRecord::Migration
def up
add_column :users, :detail, :string
end
def down
remove_column :users, :detail
end
end
change と up & down の違い
カラムの追加について、up & down記法だと6行必要な一方で、change記法だと、たった3行で済みます。
それは、change記法であれば、railsがよしなにロールバック時の処理を推測してくれるからです。
changeの内容が、「add_column」かー。
カラム追加したいってことやから、ロールバック時はカラム削除してあげたら良さそうやな!
changeの方が、以下のコマンドで一発でファイル作成してくれるし、
なにかと便利なように思えます。
だがしかし、rails も神ではない。
全て推測できるわけじゃないんです。
例えば、detailカラムのデータ型をstring → textに変えたい場合、推測はできないのです。
class ChangeColumnDetail < ActiveRecord::Migration
def change
change_column :users, :detail, :text
end
end
この記載で良いようにみえます、実際にマイグレーションも通ります。
ただ、bin/rails db:rollback
すると、怒られちゃいます。
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
This migration uses change_column, which is not automatically reversible.
To make the migration reversible you can either:
1. Define #up and #down methods in place of the #change method.
2. Use the #reversible method to define reversible behavior.
rails 様の推測は、あくまでこのファイルだけを見て行われます。
なので…
changeの内容が、「change_column」かー。
あれ待って…そしたらロールバック時って、何に戻してあげたらいいん??beforeはなんなん??
change記法だと、どう変わるかのAfterの記載しかないので、
さすがのrails様でも、何に戻してあげたらよいかのBeforeは推測できず、怒ってしまうという訳です。
なので、rails様が推測できないような場合は、up & down 記法で書かないとダメなんですねー。
class ChangeColumnDetail < ActiveRecord::Migration
def up
change_column :users, :detail, :text
end
def down
change_column :users, :detail, :string
end
end
rails 様が推測できない場合というのは、カラム削除時も該当します。
changeの内容が「remove_column」かー。
あれちょっと待って、そしたらロールバック時って、カラムを追加したらいいの??
でもどんなカラムを追加したらいいの?? 指定してくれないとそこまではちょっと…。
rails 様が推測できるかできないかなんて、こちとらわからん。
そしたらもう全部、up & down で書いちゃえばいいやんとなりそうです。