【Rails】マイグレーションファイルやschemaファイルの仕組み、rails db:migrate、rails db:rollbackとかを纏めてみた

## マイグレーションファイルとは？
マイグレーションファイルとはデータベースの設計図のことです。

このマイグレーションファイルをどのように作成して、データベースに反映させるのか、
また、一度データベースに反映させた内容をどのように修正できるのか、自分なりに纏めてみました。

## マイグレーションファイルを作成し、データベースに反映させる
まずはターミナルでマイグレーションファイル（DBの設計図）を作成します。
僕の場合、text型のbodyカラムを持つ、BoardモデルとUserモデのマイグレーションファイルを作成しました。

まずはreference型に`board_id:references`、`user_id:references`と間違った内容を付けたとします。

```terminal
# 誤った内容であることに注意！
$ rails g model comment body:text board_id:references user_id:references
```

これによって、以下のマイグレーションファイルが作成される。

```db/migrate/20200330045356_create_comments.rb
# 誤ったファイルであることに注意！
class CreateComments < ActiveRecord::Migration[5.2]
  def change
    create_table :comments do |t|
      t.text :body, null: false
      t.references :board_id, foreign_key: true
      t.references :user_id, foreign_key: true

      t.timestamps
    end
  end
end
```

このマイグレーションファイルを作成した段階では、データベースに反映されていません。
ターミナルで下記の`rails db:migrate`コマンドを実行すると、作成したマイグレーションファイルが読み込まれ、データベースに反映されます。

```
$ rails db:migrate
== 20200330045356 CreateComments: migrating ===================================
-- create_table(:comments)
   -> 0.0143s
== 20200330045356 CreateComments: migrated (0.0165s) ==========================
```

## データベースに反映されているマイグレーションファイルを確認する
そして、`rails db:migrate:status`を実行すると、DBに反映されたマイグレーションファイルを確認できます。
`up`と書いているファイルがデータベースに反映されているもの（マイグレーション済みということ）です。

```
$ rails db:migrate:status

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20200310093526  Sorcery core
   up     20200316101344  Create boards
   up     20200316105948  Add user id to boards
   up     20200328064702  Add board image to board
   up     20200330045356  Create comments
```

次に、スキーマファイルで現在のデータベースの構造を確認できるのですが、
下記のcommentsテーブルは`board_id_id`、`user_id_id`と誤ったカラムが追加されているので、修正したいです。

```db/schema.rb
# 誤ったテーブル内容
create_table "comments", force: :cascade do |t|
    t.text "body", null: false
    t.integer "board_id_id"
    t.integer "user_id_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["board_id_id"], name: "index_comments_on_board_id_id"
    t.index ["user_id_id"], name: "index_comments_on_user_id_id"
  end
```

## データベース及びマイグレーションファイルの修正方法

まずは、`rails db:rollback`で最新のマイグレーションファイルをdown状態にします。
down状態のマイグレーションファイルは、データベースに反映されていない状態にあるということです。
（up状態にあるマイグレーションファイルを削除・編集することは避けましょう）

```
$ rails db:rollback

== 20200330045356 CreateComments: reverting ===================================
-- drop_table(:comments)
   -> 0.0044s
== 20200330045356 CreateComments: reverted (0.0079s) ==========================
```

`rails db:migrate:status`で、以下の様にdown状態になったことが確認できますね。

```
$ rails db:migrate:status

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20200310093526  Sorcery core
   up     20200316101344  Create boards
   up     20200316105948  Add user id to boards
   up     20200328064702  Add board image to board
  down    20200330045356  Create comments
```

次に行う手順として、2通り方法があります。
①down状態にしたマイグレーションファイルを削除し、新しいマイグレーションファイルを作成してから、`rails db:migrate`する。
②down状態にしたマイグレーションファイルを直接編集し、`rails db:migrate`する。

どちらでもいいのですが、今回はカラム名を修正するだけなので、②の方法を取ってみます。
`board_id`を`board`に、`user_id`を`user`に変更します。

```db/migrate/20200330045356_create_comments.rb
# 誤ったファイルであることに注意！
class CreateComments < ActiveRecord::Migration[5.2]
  def change
    create_table :comments do |t|
      t.text :body, null: false
      t.references :board, foreign_key: true
      t.references :user, foreign_key: true

      t.timestamps
    end
  end
end
```

これで`rails db:migrate`すると、マイグレーションファイルがup状態に戻ります。

```
$ rails db:migrate:status

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20200310093526  Sorcery core
   up     20200316101344  Create boards
   up     20200316105948  Add user id to boards
   up     20200328064702  Add board image to board
   up     20200330045356  Create comments
```

スキーマファイルを確認すると、

```db/schema.rb
create_table "comments", force: :cascade do |t|
    t.text "body", null: false
    t.integer "board_id"
    t.integer "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["board_id"], name: "index_comments_on_board_id"
    t.index ["user_id"], name: "index_comments_on_user_id"
  end
```
無事、正しいカラム名を持ったテーブルがデータベースに反映されました！

## まとめ

最後に、ここまでの内容をまとめておきます！

- マイグレーションファイルとはデータベースの設計図のこと。
- `rails g model モデル名　カラム名:型`で、モデルとマイグレーションファイルを作成する
- `rails db:migrate`で、マイグレーションファイルをDBに反映させる(up状態)
- `rails db:rollback`で、マイグレーションファイルをDBに反映させる前の状態に戻す(down状態)
- `rails db:migrate:status`で、各マイグレーションファイルのDBへの反映状態(up,down)を確認できる
- マイグレーションファイルの修正方法は、①down状態にしたマイグレーションファイルを削除し、新しいマイグレーションファイルを作成してから、`rails db:migrate`する。もしくは、 ②down状態にしたマイグレーションファイルを直接編集し、`rails db:migrate`する。