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

# **はじめに**
マイグレーションファイルでの`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_column`を`change`メソッド内で定義してる場合はrollback実行時に、処理を反転させて勝手にremove_columnが実行されます。
しかし、change_columnの場合は、その逆処理をRailsは理解することができないため、ロールバックは失敗するということですね。

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

# **Rails関連記事**
[正規表現まとめ（基礎）[Ruby編]](https://qiita.com/takuyanin/items/2918ffb3151dcfa88565)
[配列で利用できる主なメソッドをまとめてみた[Ruby編]](https://qiita.com/takuyanin/items/3ca4cd7067b7b9e7e9b6)
[Mysql2::Error: Duplicate entry for key.. エラーを撃退した話(validationの設定)](https://qiita.com/takuyanin/items/b28d5111447d4dedc39d)
[Rails5でJqueryを利用しようとして少しハマった件（Uncaught ReferenceError: $ is not defined）](https://qiita.com/takuyanin/items/24444ec3005098471f3b)