【Rails】マイグレーションファイル［コマンドの意味や流れ］

##マイグレーションの仕組みと流れ
マイグレーションを行う際に、３つのファイルが実行される。

■マイグレーションファイル
　　データベースに対して行いたい変更を記述するもの
■スキーマファイル(``schema.rb``)
　　現状のデータベースの状態を保存するもの
■データベース

**◆流れ**
1.　マイグレーションファイルに変更内容を書く
2.　マイグレーションを実行(``db:migrate``)することで、データベースの内容が変更される
3.　変更された内容のデータベースの状態で、``schema.rb``が更新される
4.　``schema.rb``のタイムスタンプが更新される

##マイグレーションファイル作成
■新規で**モデル**から作成し、マイグレーションファイルも作成する場合。

```ターミナル.
rails g model モデル名 追加するカラム名:型（カラムは後でも書けるのでどちらでも）

#例
rails g model user name:string age:integer 
```
ここで``rails db:migrate``を行うと、マイグレーションファイルが生成される。
(今回は``name:string age:integer ``無しのモデルに何も編集していない状態で進める。)

```日付_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.timestamps
    end
  end
end
```
カラムを無しで作成すると``t.timestamps``のみがデフォルトで記載されている。
それにより、作成日時を意味する``created_at``と、更新日時を意味する``updated_at``がカラムに追加される。

■モデルは既にあって、カラムを追加したいからマイグレーションファイルだけ作成する場合。

```ターミナル.
rails g migration Add 追加するカラム名 To 追加するテーブル名 追加するカラム名:型（カラムは後でも書けるのでどちらでも）

#例
rails g migration AddEmailToUsers email:string
```

あとはバリデーションを追記するなりして``rails db:migrate``をすればカラムが追加される。ただし追加だけでなく既にあるファイルを変更となると、ファイルのステータスから見ないといけない。

##マイグレーションファイルのステータス
マイグレーションファイルにはステータスが存在する。
ステータスは``rails db:migrate:status``コマンドで確認できる。

```ターミナル.
$ rails db:migrate:status

Status   Migration ID    Migration Name
--------------------------------------------------
   up     20190501111550  Create blogs
   up     20190501123505  Change blogs title not null
  down     20190501123715  Change blogs content not null
  down     20190502033857  Create comments
```

このステータス画面では、**どのマイグレーションファイルが実行中で、どのファイルが実行されていないか**が分かる。

``up``が実行中で、``down``が実行されていない状態である。
マイグレーションを実行(``db:migrate``)することで、``up状態``になる。
このマイグレーションファイルの``up/down``の状態が重要になってくる。

例えば、マイグレーションファイルの変更を行いたいときなどにステータスの有無が必要になってくる。

##マイグレーションファイルの変更を行う場合
仮に``userテーブル``にカラムを追加・変更を実施する際に、マイグレーションファイルのステータスを**``down``**にしなければならない。

``up状態``で、マイグレーションファイルに変更を加えて、``rails db:migrate``を実施しても全く反映されない。(装備中の防具を外さないと新しい装備が付けれない的な)

``down状態``にするには、コマンドで``rails db:rollback``を実行すればできる。変更を施した後、また``rails db:migrate``を行えば``up状態``になる。

**⚠️注意**
マイグレーションファイルは基本的に上から（時間順）に実行されていく。``rollback``は反対の下から（最新時間順）から１個のファイルのみ``down``になるので、変更したいファイルまで飛ばしたい場合にはSTEP数を指定してロールバックする。もしくは``Migration ID``を指定して行う。

```ターミナル.
#STEP数を指定してロールバック
$ rails db:rollback STEP=ステップ数

#Migration IDを指定してロールバック。IDはステータスで確認できる。
$ rails db:migrate:down VERSION=oooooooooo
```

##up状態のマイグレーションのファイルを削除すると「NO FILE」ができる
もし不要なマイグレーションファイルがあって削除する場合、``down状態``で削除したらいいが、``up状態``のまま消してしまうと以下のようになる。

```ターミナル.
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20190915023701  Create posts
   up     20190915065320  ********** NO FILE **********
  down    20190915080932  Devise create users
```

この``NO FILE``を削除する方法として、ダミーファイルを作成し、そのファイルを削除することで解決する。

``Migration ID``をコピーしてダミーファイルを作成。(名前は適当でOK)

```ターミナル.
touch db/migrate/20190915065320_hoge.rb
```

ダミーファイルが作成できたら、ちゃんと``NO FILE``だったところに割り当てられているか確認する。

```ターミナル.
Status   Migration ID    Migration Name
--------------------------------------------------
   up     20190915023701  Create posts
   up     20190915065320  Hoge
  down    20190915080932  Devise create users
```

確認できたら、このダミーファイルを``down状態``にし、削除すれば良い。

```ターミナル.
$ rails db:migrate:down VERSION=20190915065320

$ rm db/migrate/db/migrate/20190915065320_hoge.rb
```

##コマンド集
マイグレーション関連コマンド集

| コマンド| 意味・機能 |
|:-:|:-:|
| rails g migration クラス名  | マイグレーションファイル作成  |
| rails g model モデル名  | モデル作成  |
|  rails db:migrate | マイグレーション実行  |
|rails db:migrate:status|ステータス確認|
|  rails db:rollback |   ロールバック|
| rails db:rollback STEP=ステップ数 | STEP数を指定してロールバック  |
| rails db:reset  |  全てのDBを削除した後に、schema.rbを元にDB作成 |
|rails db:migrate:reset|全てのDBを削除した後に、db/migrate/**.rb を元に古い順から実行|

##参考記事
[Ruby on Rails 『NO FILEのmigrationを削除する方法』](https://qiita.com/sakatan_1/items/9bf321f81d3b84042694)
[[Rails]マイグレーションファイルについて勉強してみた！(テーブルへのカラム追加)](https://qiita.com/jackie0922youhei/items/09a7b081e40506f07358#:~:text=%E3%83%9E%E3%82%A4%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%A8%E3%81%AF,%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%8C%E7%94%9F%E6%88%90%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82)
[Rails：マイグレーションファイル、スキーマファイル におけるタイムスタンプの役割](https://qiita.com/sobameshi0901/items/f5823fec20e2dd78d9c4)
[rails generate migrationコマンドまとめ](https://qiita.com/zaru/items/cde2c46b6126867a1a64)
[rails db:migrate:resetできなかったのでrails db:resetした](https://qiita.com/mom0tomo/items/a252ff8a42eea00f81b1)