【Rails】初心者向け！データベースで困った時の味方！

始めまして！
adventカレンダー3日目を担当させていただきます。
DMM WEBCAMPでメンターをしている吉村です！

よろしくお願いします！

# はじめに
Rails始めたばかりの頃、データベースがらみが全く理解できず、
よく夜遅くまで、悩まされたことを覚えています。。。
今回はそんなRails初心者の方向けに、
データベースとはなんぞや！といった仕組みから
具体的なコマンドを一挙に説明・紹介していきたいと思います！

# Railsのデータベースってどんな構造なの？!
Railsのデータベースは大きく2つのファイルから成り立っています。
**マイグレーションファイル**と**スキーマファイル（schema.rb）**です。

まずは、**マイグレーション**とはなんなのかから解説していきたいと思います。
マイグレーションとは
>マイグレーションは、データベーススキーマの継続的な変更 (英語) を、統一的かつ簡単に行なうための便利な手法です。
引用：[Railsガイド](https://railsguides.jp/active_record_migrations.html)

よくわかりませんよね笑

本来であれば、テーブルを作成するには、SQL文を直接実行して作成する必要があります。
カラムを追加したりする場合も同じです。
対して、マイグレーションを使う場合は、テーブルを新規作成するためのマイグレーションファイルを作成し、実行します。
カラムを追加する際も同じようにマイグレーションファイルを作成します。

### マイグレーションのイメージ
マイグレーションを超簡単に図解すると、
![無題のプレゼンテーション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/905847/12d92fa0-4615-ce29-2c04-54386d1f4bd5.png)
このようになります。
家に例えると、マイグレーションファイルは、家をどんな構造にするかを示した設計図のようなものです。
そして、``rails db:migrate``と言うコマンドを実行することで、その設計図に従って家が建てられます。なので、schemaに記述されているものが実際に作られたデータベースの形になります。
※実際はschemaに直接データが保存される訳ではないですが、今回は初心者向けの記事になるのでわかりやすいよう家と表現しています。
逆に家を壊すコマンドもあります。それが、``rails db:rollback``と言うコマンドです。
これを実行すると家が壊すことができます。
この辺のコマンドの使い方はあとで詳しく説明します！

### マイグレーションの利点
一見マイグレーションと言う機能は面倒に見えますが、この機能を使うことで特定のデータベースの文法に依存せずにテーブルへ行なう操作を記述でき、変更を実施したり元に戻すといった作業が簡単に行なえるようになります。

# マイグレーションで使えるコマンド
では、マイグレーションの基礎知識がわかったところで、具体的にどんなコマンドがどんな場面で使えるのかを説明していきます。

### rails db:migrate
このコマンドは一番基本的なコマンドになります。
先ほど少し書いた通り、このコマンドを実行することで初めてマイグレーションファイルをもとにデータベースが作成されます。
そして、どんな形のデータベースができたかが確認できるファイルがスキーマファイルになります。
皆さんにも馴染みのあるコマンドだと思います。 

```
== 20200818105133 CreateOrderDetails: migrating ===============================
-- create_table(:order_details)
   -> 0.0033s
== 20200818105133 CreateOrderDetails: migrated (0.0034s) ======================

== 20200819150420 CreateAddresses: migrating ==================================
-- create_table(:addresses)
   -> 0.0066s
== 20200819150420 CreateAddresses: migrated (0.0068s) =========================
```

実際にコマンドを打ち込んでみるとこんな処理が走るはずです。
`create_table`と言う処理が確認できますね。
これでテーブルが正常に作成できたことがわかります。

### rails db:migrate:status
とりあえず、データベース関連で困ったときはこのコマンドを打ち込みましょう！
このコマンドは今どのマイグレーションファイルまで、``rails db:migrate``が行われているかを確かめるコマンドです。

```
Status   Migration ID    Migration Name
--------------------------------------------------
   up     20200729160256  Devise create end users
   up     20200729160307  Devise create admins
   up     20200812043150  Create items
   up     20200812045123  Create genres
   up     20200817101827  Create cart items
  down    20200818103251  Create orders
  down    20200818105133  Create order details
```
実際にコマンドを打ち込むと、このように今あるマイグレーションファイルの一覧が出てきます。
ここで注目したいのが一番左側にある`Status`の部分です。
ここが**up**になっていると言うことは、``rails db:migrate``がすでに実行されている状態を表します。
ので、**設計図（マイグレーションファイル）**をもとに**家（schema）**が建っている状態ですね。

反対に、**down**になっていると言うことは、``rails db:migrate``がまだ実行されていない状態を表します。
ので、まだ設計図を作っただけの状態です。
マイグレーションファイルを編集する時は、Statusが**down**になってることを確認してから行いましょう。（理由は後述します。）

### rails db:rollback
マイグレーションファイルを作成し``rails db:migrate``をした後(Statusがup)に、「カラムを追加したい」「テーブルの中身を書き換えたい」と思った時に使えるコマンドです。
カラムを追加したい時は、直接マイグレーションファイルやスキーマファイルを編集すればいいんじゃないかと思うかもしれませんが、ここで注意です！
まず、スキーマファイルはマイグレーションファイルに従って作られるものなので、基本的に**直接書き換えることはないです！**
次にマイグレーションファイルを編集すると言う方法なのですが、これは可能です！ただし、`rails db:migrate`される前（Statusがdown）であることが条件です。
``rails db:migrate``をした後(Statusがup)の時にマイグレーションファイルを書き換えても設計図だけ書き換わっただけの状態になり実際のデータベースの形は変わりません！
なので、一度Statusをdownにする必要があります。
それをするためのコマンドがこの`rails db:rollback`になります。

```
== 20200819150420 CreateAddresses: reverting ==================================
-- drop_table(:addresses)
   -> 0.0038s
== 20200819150420 CreateAddresses: reverted (0.0053s) =========================
```

実際にコマンドを打ち込んでみるとこんな処理が走るはずです。
`drop_table`と言う処理が確認できますね。
これでテーブルが正常にもとに戻すことができたことがわかります。
この状態になって初めてマイグレーションファイルを書き換えることができます。
さらに、通常`rails db:rollback`は一番最近マイグレイションされたファイルを１つだけもとに戻すものなのですが、
`rails db:rollback STEP=○`と任意の数字を指定してあげると、一気に2つ以上のファイルをもとに戻してくれたりもします。
※チーム開発をしてる時に、rollbackを使ってマイグレーションファイルを書き換えるとコンフリクトが起こりますので、注意してください。チーム開発の場合はマイグレーションファイルを新たに作成してカラムを追加したり、削除したりしましょう。
参考：[マイグレーションファイルの作成、変更、削除まで](https://qiita.com/fujiab/items/b744fdcd2f8d3686d4ca)

### rails db:migrate:reset
このコマンドはデータベースを一度全てリセットして、マイグレーションファイルをもとに再度作り直すコマンドです。
似たようなコマンドに`rails db:reset`がありますが、これはスキーマファイルをもとにデータベースを作り直すコマンドで、今あるデータベースの形のままデータだけをリセットしたい時に使います。
基本的には`rails db:migrate:reset`を実行してもらえば間違い無いです。

# 最後に
いかがだったでしょうか。
マイグレーションファイルやらスキーマファイルやら、カタカナや英語がいっぱい出てきて混乱したかと思いますが、少しずつデータベースにも慣れていきましょう。
データベースは直接書き換えるよりかは、コマンドで実行することが多いので、不安になる気持ちもありますが、適切なコマンドを適切なタイミングで使えるようになると、もっと楽しくなると思います！

それでは、失礼します！