はじめに
マイグレーションファイルでのchange
メソッドはmigrate
を実行したときの処理を定義するものであり、とても便利なメソッドですよね。
マイグレーションファイルでよく利用するメソッドの他にup
メソッドとdown
メソッドがありますが、こちらと違うところは、change
メソッドはrollback時の処理を勝手に反転して実行してくれるところです。
ですので、change
メソッドはrollback
時の処理を書く必要はありません。
しかし、メソッド内で**change_column
で記述した場合はrollbackする際にエラーが出ます。**
その際の解決方法を備忘録として記しておきます。
問題
class ChangeLimitOfMessageLength < ActiveRecord::Migration[5.2]
def change
change_column :info_emails, :message, :text, limit: 500
end
end
$ rake db:migrate
(in /Users/takuyanin/projects/MailApp)
== 20181204174549 ChangeLimitOfMessageLength: migrating =======================
-- change_column(:info_emails, :message, :text, {:limit=>500})
-> 0.1817s
== 20181204174549 ChangeLimitOfMessageLength: migrated (0.1819s) ==============
マイグレーションを実行した後に、ロールバックしてマイグレーションを取り消す際に下記のエラーが出ました。
$ rake db:rollback
(in /Users/takuyanin/projects/MailApp)
== 20181204174549 ChangeLimitOfMessageLength: reverting =======================
rake aborted!
StandardError: An error has occurred, 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.
/Users/takuyanin/projects/MailApp/db/migrate/20181204174549_change_limit_of_message_length.rb:3:in `change'
Caused by:
ActiveRecord::IrreversibleMigration:
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.
/Users/takuyanin/projects/MailApp/db/migrate/20181204174549_change_limit_of_message_length.rb:3:in `change'
Tasks: TOP => db:rollback
(See full trace by running task with --trace)
解決
This migration uses change_column, which is not automatically reversible.
解決策が明記されていますね。この記述の下の二つの解放のうち好きな方法で解決すると良いでしょう。
今回は、最初の方の解法でいくとします。up
メソッドとdown
メソッドをchange
メソッドの代わりに定義しなさい、と書いてありますが、今回はchange
メソッドをup
メソッドに書き換えるだけで解決します。
class ChangeLimitOfMessageLength < ActiveRecord::Migration[5.2]
def up
change_column :info_emails, :message, :text, limit: 500
end
end
上記のように書き換え、再度ロールバックを実行します。
$ rake db:rollback
(in /Users/takuyanin/projects/MailApp)
== 20181204174549 ChangeLimitOfMessageLength: reverting =======================
== 20181204174549 ChangeLimitOfMessageLength: reverted (0.0000s) ==============
成功しました。
$ rake db:migrate:status
(in /Users/takuyanin/projects/MailApp)
database: MailApp_development
Status Migration ID Migration Name
--------------------------------------------------
up 20181012061507 Devise create users
.
.
.
up 20181204171408 Create info emails
down 20181204174549 Change limit of message length
rake db:migrate:status
コマンドで確認すると、きちんとdown
に変更されてますね。
あとは、手動でこのマイグレーションファイルを削除すればOKです。
まとめ
add_column
をchange
メソッド内で定義してる場合はrollback実行時に、処理を反転させて勝手にremove_columnが実行されます。
しかし、change_columnの場合は、その逆処理をRailsは理解することができないため、ロールバックは失敗するということですね。
少しでも役にたったよー。て方はいいねお願いします(^^)
Rails関連記事
正規表現まとめ(基礎)[Ruby編]
配列で利用できる主なメソッドをまとめてみた[Ruby編]
Mysql2::Error: Duplicate entry for key.. エラーを撃退した話(validationの設定)
Rails5でJqueryを利用しようとして少しハマった件(Uncaught ReferenceError: $ is not defined)