Railsのマイグレーション管理方法について

#まえがき
Railsのマイグレーション管理する方法についての個人的なめも。
賛否両論あると思いますが、まとめておきたいと思い、書いてます。
※誤記・不足あれば、ご支援いただけると助かります。

#環境
Ruby 2.6.3
Rails 5.2.3
MySQL 5.7.25

#状況
すでにモデルが一つ存在する状態での、カラム追加を想定しています。

◆Userモデル（Usersテーブル）

|項目名|DBカラム名|型|補足|
|:-:|:-:|:-:|:-:|
|名前|name|String||

```mysql
mysql> desc users;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | YES  |     | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
```

◆Migrationファイル

```ruby:db/migrate/20190813002037_create_users.rb
class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      t.string :name

      t.timestamps
    end
  end
end
```

この状態の時、以下のカラムを追加したい場合。

|項目名|DBカラム名|型|補足|
|:-:|:-:|:-:|:-:|
|年齢|age|Integer||

#方法１：マイグレーションファイルを追加していく方法（推奨）
メリット：既存データへの影響を少なくしてDB構成を変更出来ます。
　※既にリリースしたサービスであれば、これが有効
デメリット：変更があるたびにマイグレーションファイルが追加されるため、ファイルが多くなり管理が難しくなります。
　※現在のDB状態を見るには、DBを直接確認するか、db/schema.rbを確認しましょう。

##rails g migrateを使って、追加します

```ruby
rails g migration AddAgeToUser age:integer
```

コマンドひとつで、マイグレーションファイルが出来上がります。
※コマンドを実行した後に、作成されたファイルを修正するでも構いません。

```ruby:db/migrate/20190813002439_add_age_to_user.rb
class AddAgeToUser < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :age, :integer
  end
end
```

##rake db:migrateで、DBに反映します

```ruby
$ rake db:migrate
== 20190813002439 AddAgeToUser: migrating =====================================
-- add_column(:users, :age, :integer)
   -> 0.0376s
== 20190813002439 AddAgeToUser: migrated (0.0377s) ============================

```

ageが追加されました。

```mysql
mysql> desc users;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | YES  |     | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
| age        | int(11)      | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
```

#方法２：既存マイグレーションファイルを修正する方法
メリット：マイグレーションファイルが１テーブル１ファイルになり、管理がし易くなります。
　※このテーブルを修正したい場合はこのファイル！といった管理がし易くなります。
デメリット：反映時に既存データが消えるため、必要なデータについては、一旦退避するなどの対応が必要です。
　※既にリリースしたサービスであれば、データ損失にもつながるので、推奨しません。

##既存マイグレーションファイルを直接修正します
```ruby:db/migrate/20190813002037_create_users.rb
class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      t.string :name
      t.integer :age     # ここを追加

      t.timestamps
    end
  end
end
```
##rake db:migrate:resetで、DBに反映します

```ruby
$ rake db:migrate:reset
Dropped database 'migration_sample_development'
Dropped database 'migration_sample_test'
Created database 'migration_sample_development'
Created database 'migration_sample_test'
== 20190813002037 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0160s
== 20190813002037 CreateUsers: migrated (0.0161s) =============================
```

ageが追加された状態で再作成されます。

```mysql
mysql> desc users;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | YES  |     | NULL    |                |
| age        | int(11)      | YES  |     | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
```

注意：
方法１と方法２では、ageの追加位置が違いますが、方法１でも追加位置を指定する事は可能です。

#個人的な使い分け
最初のリリースまでは、方法２のパターンを使い、リリースした後からは方法１を使っています。

最初にきっちりDB構成を決めておけば、マイグレーションファイルの数を最小限に減らせると思いますが、
そんな簡単ではないですし、開発していくにつれ、「これもいる・これはいらない」というのがどうしても出てきてしまうと思います。
そのため、このような使い分けを私は使っています。