マイグレーション基礎知識のまとめ　rails db:rollbackとカラムの追加/削除

# はじめに
【この記事から得られる知識】
・マイグレーションについて
・rails db:rollbackの実行手順
・カラムの追加と削除の実行手順
・カラムがreferences型の場合の追加と削除の実行手順

【環境】
・macOS Catalina
・rails 6.0.0
・ruby 2.6.5

# マイグレーションとは
・テーブルの設計図や仕様書のこと　
・データベースにテーブルを作成する際に重要な役割をもっている
　-マイグレーションファイルにカラムの型、カラム名、オプションの情報を記述する
　-情報を反映させるとテーブルの作成・変更ができる
# マイグレーションの実行手順
①モデルを作成
②モデル作成時に生成されるマイグレーションファイル（db/migrate/2020~~~~.rb)に必要な情報を記述する

```ruby:db/migrate/20201014123456_create_address.rb
class CreateAddresses < ActiveRecord::Migration[6.0]
  def change
    create_table :addresses do |t|
    # t.カラムの型 :カラム名, 　　　　オプション
      t.string :postal_code,    null: false
      t.string :city,           null: false
      t.string :address_line,   null: false
      t.string :phone_number,   null: false
      t.references :order,      null: false, foreing_key: true
      t.timestamps
    end
  end
end
```
③記述したテーブルのカラムを反映させるために作成中のアプリケーションのディレクトリにいることを確認した後ターミナルでrails db:migrateを実行

```terminal
% rails  db:migrate
```
④ターミナルに以下のような記述があれば成功！

```terminal
== 20XXXXXXXXXXXX CreateAddresses: migrating ======================================
-- create_table(:addresses)
   -> 0.0395s
== 20XXXXXXXXXXXX CreatePosts: migrated (0.0396s) =============================
```

念のためsequelproでも記述した情報が表示されていれるか確認する
※情報が反映されていない場合は更新ボタンをクリックする
***
### せっかくrails db:migrateしたのにテーブルにミスがあった！
「どうしよう、、、」
「マイグレーションを編集したいっ！」ていうときありますよね。

しかし、一度実行すると再度実行できない仕組みになっています。
なぜかというと設計を履歴として残しあとでどのような変更をしたか確認できるようにするためです。

もしスペルミスでカラム名を変更したい場合であればわざわざ履歴に変更を残したくないですよね。

その場合は```rails db:rollback コマンド```を使いましょう。（反映済みの情報を差し戻すことができるため変更の履歴が残りません。）
それ以外の場合は**カラムの追加/削除用のマイグレーションファイルを作成**して変更を行いましょう。（新たにファイルを作成して変更をするため履歴が残ります。）



以下でこれらの説明をしたいと思います。

***

# rails db:rollback 実行手順①~⑥
①```rails db:migrate:statusコマンド```でマイグレーションファイルの状況を確認

```terminal
% rails db:migrate:status
```
・実行するとマイグレーションの履歴が表示され、statusがupとdownで状況が表示される
・upは実行済み、downは修正可能の状態を意味する

```terminal
# rails db:migrate:stauts 実行結果

database: アプリ名_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20201001015223  Create orders
   up     20201001092756  Create addresses
   up     20201014023427  Add id to addresses
   up     20201014030100  Add id to orders
```
②```rails db:rollback```を実行してup(実行済み)をdown(修正可能)にする

```terminal
% rails db:rollback
```
③もう一度```rails db:migrate:status```を実行しマイグレーションファイルの状況を確認する

```
database: アプリ名_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20201001015223  Create orders
   up     20201001092756  Create addresses
   up     20201014023427  Add id to addresses
  down    20201014030100  Add id to orders
```
④変更したいマイグレーションファイルのstatusがdownであることが確認できると今回の場合db/migrate/2020101430100_~~.rbのファイルを修正する
⑤```rails db:migrate```を実行し修正内容を反映させる

```terminal
% rails  db:migrate
```
⑥念のためsequelproでも記述した情報が表示されていれるか確認する
※情報が反映されていない場合は更新ボタンをクリックする

### 【補足情報】
任意のマイグレーションファイルをrollbackしdownの状態にしたい場合は
```rails db:rollback STEP=数値(戻りたい箇所が下から数えて何番目か)```というふうに記述し実行する
※一番下を1とする

```terminal
# 下から2番目をrollbackしたい場合 
% rails db:rollback STEP=2
```
statusを確認すると下から2番目までdownになっていることが確認できる

```
database: アプリ名_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20201001015223  Create orders
   up     20201001092756  Create addresses
  down    20201014023427  Add id to addresses
  down    20201014030100  Add id to orders
```

後は同じようにマイグレーションファイルを修正し```rails db:migrate```を実行する
# カラムの追加/削除 実行手順（パターン1, 2）
最初に前提の知識としてカラムの追加は```add_column```カラムの削除は```remove_column```と記述する

```ruby
    # カラムの追加
    add_column :users, :first_name, :string
    # カラムの削除
    remove_column :users, :last_name, :string
```
### パターン1 : 順番に記述する方法

①```rail g migration ファイル名```を実行
ファイル名は```Addカラム名To追加先のテーブル名```とする（ファイル名は任意のものでもいいが、Add~To~が後から見たときにわかりやすく定着したファイル名のつけ方になっている)

```terminal
# nameカラムをUsersテーブルに追加する場合
% rails g migration AddNameToUsers
```
生成されるファイルの中身

```db/migrate/20200000000000_add_names_to_users.rb
class AddNamesToUsers < ActiveRecord::Migration[6.0]
  def change 
  end
end
```
②新しく生成されたマイグレーションファイルに情報を記述する

```db/migrate/20200000000000_add_names_to_users.rb
class AddNamesToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :first_name, :string
    add_column :users, :last_name, :string
  end
end
```
③```rails db:migrate```を実行する

```terminal
% rails  db:migrate
```

### パターン2 : ターミナルにまとめて記述する方法

①```rail g migration ファイル名 追加するカラム名:型 ```を実行

```terminal
# 追加するカラムの詳細情報までまとめ記述する
% rails g migration AddNameToUsers first_name:string last_name:string
```
生成されるファイルの中身（ファイルの中身が記述された状態でマイグレーションファイルが生成）

```db/migrate/20200000000000_add_names_to_users.rb
class AddNamesToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :first_name, :string
    add_column :users, :last_name, :string
  end
end
```
②```rails db:migrate```を実行する

```terminal
% rails  db:migrate
```
# references型カラムの追加/削除 実行手順


状況：Ordersテーブルに外部キーとしてaddress_idを追加する

①```rails g migration ファイル名```を実行する

```terminal
# address_idカラムをOrdersテーブルに追加する場合
% rails g migration AddIdToOrders
```
②生成されたファイルに記述する

```ruby:db/migrate/20201014000000_add_id_to_orders.rb
class AddIdToOrders < ActiveRecord::Migration[6.0]
  def change
    # 追加
    add_reference :orders, :address, foreign_key: true
    # 削除
    remove_reference :orders, :address, foreign_key: true
  end
end
```
追加のポイント
・```add_reference```であること
・```foreign_key: true```を記述すること（必要な場合のみ）
削除のポイント
・```remove_reference```であること

③```rails db:migrate```を実行する

```terminal
% rails  db:migrate
```

解説は以上です！！

想像より長くなってしまいましたがこの記事がお役に立てると幸いです。
慣れると簡単なのでぜひ習得してスムーズに開発が進められるようにしましょう！
それでは、最後までご覧いただきありがとうございました。

# 参考
・https://qiita.com/kurawo___D/items/e3694f7a870a1cc4738e
・https://freesworder.net/rails-column-add-remove/
・https://gist.github.com/seak0503/84bfa6b37a0a6961c334