railsのマイグレーションを指定バージョンまで戻す方法

# 使用技術

* ruby(rails)
* mysql
* vscode



# 経緯

認証機能を簡単に実装できるdeviseのgemを導入する。
しかし、既存の認証処理を書いたコードが干渉してか上手く動作しなかった。
そこでgitを使って元のコードに戻すことに。

vscodeの拡張機能で、ファイルの変更履歴は把握できているので
gitで戻せなかった分は個別削除で対応できた。
残るはマイグレーション…

当記事では、**`マイグレーションを戻す作業で`**
少し行き詰まったので、自分の対応記録として残す。



# 状況把握

まず、過去のマイグレーション状況を確認する。

```zsh:ターミナル
% rails db:migrate:status


↓出力結果↓

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20210627055651  Add columns to users
   up     20210628231142  Add columns to articles
   up     20210630002331  Create comments
   up     20210701024750  Create likes
   up     20210701235655  Create bookmarks
```

次に、現在はどのマイグレーションまで反映されているか確認する。


```zsh:ターミナル
% rails db:version


↓出力結果↓

Current version: 20210701235655
                 ↑ 現在のMigrationID
```



# マイグレーションを戻す

ステータスで確認した状況をもとに、指定した状態まで戻す。

下記コマンドと打つと、私のマイグレーション状況で表すと
`１つ前のマイグレーション`である`「20210701024750  Create likes」`まで
戻すことを意味している

※ **reverting：元に戻す**　→ 思った通りに動いているっぽい。

■メモ：
「rails db:rollback STEP=1」コマンドを、`STEP=2`に変更すれば
`２つ前のバージョンに戻す`ので適宜で変更する。

```zsh:ターミナル
% rails db:rollback STEP=1


↓出力結果↓

== 20210701235655 CreateBookmarks: reverting ==================================
-- remove_index(:bookmarks, [:article_id, :user_id], {:unique=>true})
   -> 0.0070s
-- remove_index(:bookmarks, :user_id)
   -> 0.0048s
-- remove_index(:bookmarks, :article_id)
   -> 0.0058s
-- drop_table(:bookmarks)
   -> 0.0049s
== 20210701235655 CreateBookmarks: reverted (0.0244s) =========================
```

現状を確認するコマンドで確かめてみると
Statusが　**`down`**　に変更されている

```zsh:ターミナル
% rails db:migrate:status 


↓出力結果↓

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20210627055651  Add columns to users
   up     20210628231142  Add columns to articles
   up     20210630002331  Create comments
   up     20210701024750  Create likes
  down    20210701235655  Create bookmarks
```

さらにrails db:versionで現在のマイグレーションを確認する

```zsh:ターミナル
% rails db:version 


↓出力結果↓

Current version: 20210701024750
```



# マイグレーションファイルの削除

不要になったマイグレーションファイルを削除する。
(コマンドに拘らず、GUIで削除してもいい)


```zsh:ターミナル

% rm -rf db/migrate/消したいマイグレーションファイル名


```

# マイグレーションを反映する

db/migrateのディレクトリ内に残っているマイグレーションファイルを元にマイグレーションを反映させる。

```zsh:ターミナル

% rails db:migrate

```



# 補足

おそらく、上記コマンドで上手く動作する。

もしかしたら、deviseのgemを導入時に
マイグレーションを戻す際に制限コードが含まれていて
エラーを発生させてくる可能性あるのかも。

そうであれば、発生原因のマイグレーションファイルを
コメントアウトなどで干渉しないようにすれば通るかも。




# （参考）マイグレーションファイルの編集

当記事は、削除が目的であったが、
間違ったマイグレーションファイルを正しく修正したい場合も
バージョンを戻す作業は活用できる。

ただし、実行する作業の順序には注意する。

特に
`・マイグレーションファイル編集の後　→ rails db:rollback STEP=1コマンド`　**`ではなく`**
`・rails db:rollback STEP=1コマンドの後 → マイグレーションファイル編集　`
で実行しないとエラー出てハマる。

また、マイグレーションファイルは
RailからMySQL内でデータベースを生成する際に使うもの。
あくまでMySQLは別空間にあるものをイメージしておく。

そのため、
`・対象のマイグレーションファイルを編集した後`
`・MySQL内にあるテーブルを削除し`
`・編集後のマイグレーションファイルを反映`
が良い。
（MySQL内のテーブル削除を省くと、migrationとMySQLの整合性が合わずエラー出る）

上記の懸念事項を配慮して、実行する作業が下記のもの。


```zsh:ターミナル
# 一つ前のマイグレーションのバージョンを戻す
% rails db:rollback STEP=1

# ファイルを開いて編集する
エディター：マイグレーションファイルの編集
　例）テーブルに必要なカラムを追加、テーブルの不要なカラムを削除…など

# MySQLにログイン(ローカル環境の場合)
% mysql -u ユーザー名 -pパスワード
# (Docker環境の場合)
% docker container exec -it DBコンテナ名称 bash

# MySQLから対象のテーブルを削除する
mysql> DROP TABLE データベース名.テーブル名;

# 対象テーブルが存在しないか確認する
mysql> SHOW TABLES;

# MySQLから抜ける
mysql> exit

# 編集したマイグレーションファイルを反映させる
% rails db:migrate

```

もし、マイグレーションファイル編集後にバージョン戻してエラーになった場合は、
落ち着いて、現状でMySQL生成済みのマイグレーションファイルの状態にコードを戻して
再度バージョンを戻すコマンドを実行すれば上手くいく…はず。

# コマンド一覧

マイグレーション関係のコマンド一覧をまとめておく。

```zsh:ターミナル

# データベースの新規作成
% rails db:create

# マイグレーションファイルを使ってデータベースに反映させる
% rails db:migrate
　
# 実行環境を指定してマイグレーションする
% rails db:migrate RAILS_ENV=test | production

# 過去のマイグレーション状況を確認
% rails db:migrate:status
　
# 現在のマイグレーションのバージョンを確認
% rails db:version

# マイグレーションを初期化
% rails db:migrate VERSION=0

# 一つ前のマイグレーションに戻す
% rails db:rollback
　
# n個前までのマイグレーションに戻す
% rails db:rollback STEP=数字

# 全てテーブルをリセットして再構築する
% rails db:migrate:reset

# テスト用データを流す
% rails db:seed

```


# おわりに

deviseの導入が失敗し、コードを元に戻したいが上手くいかない…
といった面倒な状況だったが、gitコマンドやマイグレーションの理解に繋がったので良しとしよう。
何事も取り組み続ければ解決できるはず！

最後までお読み頂き、ありがとうございました！！！！！