Edited at

【Ruby on Rails】changeとup・downの使い分けについて

スクールで学習していたときにはchangeのみしか扱っておらず、up・downとの違いがわかりにくい部分があったのでメモしておきたいと思います。

初投稿が故、マークダウンの練習も兼ねています。


そもそもup・downって?

マイグレーションファイルのchangeメソッドではバージョンを上げるときの処理を書いておけば、下げるとき(ロールバック)の処理も記述したかのように動作してくれる仕組みになっているらしい。

ただし、変更内容によっては下げるときの処理も別で書く場合もあり、その際にはupメソッドとdownメソッドという形で書くとのこと。


changeを使う場合

単純にカラムを追加するとき(add_column)であれば、changeで記述してもバージョンを下げる処理を行うことができます。命名規則に従うだけで内容まで記述されたマイグレーションファイルが生成されるのは便利ですね。


20190217071419_add_detail_to_user.rb

class AddDetailToUser < ActiveRecord::Migration[5.2]

def change
add_column :users, :detail, :string
end
end


up・downを使う場合

カラムの変更(change_column)の場合、changeメソッドで記述するとバージョンを下げる処理を生成してくれません。downを使ってバージョンを下げる際の処理を書きます。


20190217072540_change_column_to_user.rb

class ChangeColumnToUser < ActiveRecord::Migration[5.2]

def up
change_column :users, :detail, :text
end

def down
change_column :users, :detail, :string
end
end



マイグレーション

$ bin/rails db:migrate

== 20190217072540 ChangeColumnToUser: migrating ===============================
-- change_column(:users, :detail, :text)
-> 0.0025s
== 20190217072540 ChangeColumnToUser: migrated (0.0031s) ======================


ロールバック

$ bin/rails db:rollback

== 20190217072540 ChangeColumnToUser: reverting ===============================
-- change_column(:users, :detail, :string)
-> 0.0010s
== 20190217072540 ChangeColumnToUser: reverted (0.0017s) ======================

ロールバックも正しく行えているようです。


changeで書くとどうなるか


20190217080251_change_column_to_user2.rb

class ChangeColumnToUser2 < ActiveRecord::Migration[5.2]

def change
change_column :users, :name, :string, limit: 20
end
end

$ bin/rails db:migrate

== 20190217080251 ChangeColumnToUser2: migrating ==============================
-- change_column(:users, :name, :string, {:limit=>20})
-> 0.0435s
== 20190217080251 ChangeColumnToUser2: migrated (0.0442s) =====================

マイグレーションはできる、が、

$ bin/rails db:rollback

== 20190217080251 ChangeColumnToUser2: reverting ==============================
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

(以下略)

ロールバックができません。たしかにchangeメソッドだと変更前のカラムの情報がないのでロールバックできないのも道理ですね。

マイグレーションまではできてしまうのでうっかりミスしても気づかない可能性があるので気を付けたいところです。

以下のコマンドを使うとロールバックしてからもう一度マイグレーションしてくれるので確認が楽になります。

$ bin/rails db:migrate:redo


最後に

初投稿でした。

何か捕捉の情報や修正などありましたら、コメント欄にてご指摘頂けますと幸いです。


参考にした記事

RailsのMigrationに関する基本まとめ