LoginSignup
76
49

More than 5 years have passed since last update.

change_columnでの設定はrollbackできない話(This migration uses change_column, which is not automatically reversible.)[Rails]

Last updated at Posted at 2018-12-05

はじめに

マイグレーションファイルでのchangeメソッドはmigrateを実行したときの処理を定義するものであり、とても便利なメソッドですよね。
マイグレーションファイルでよく利用するメソッドの他にupメソッドとdownメソッドがありますが、こちらと違うところは、changeメソッドはrollback時の処理を勝手に反転して実行してくれるところです。
ですので、changeメソッドはrollback時の処理を書く必要はありません。

しかし、メソッド内でchange_columnで記述した場合はrollbackする際にエラーが出ます。
その際の解決方法を備忘録として記しておきます。

問題

20181204174549_change_limit_of_message_length.rb
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メソッドに書き換えるだけで解決します。

20181204174549_change_limit_of_message_length.rb
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_columnchangeメソッド内で定義してる場合はrollback実行時に、処理を反転させて勝手にremove_columnが実行されます。
しかし、change_columnの場合は、その逆処理をRailsは理解することができないため、ロールバックは失敗するということですね。

少しでも役にたったよー。て方はいいねお願いします(^^)

Rails関連記事

正規表現まとめ(基礎)[Ruby編]
配列で利用できる主なメソッドをまとめてみた[Ruby編]
Mysql2::Error: Duplicate entry for key.. エラーを撃退した話(validationの設定)
Rails5でJqueryを利用しようとして少しハマった件(Uncaught ReferenceError: $ is not defined)

76
49
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
76
49