【勉強メモ】Railsマイグレーションの仕組み

# 本記事の目的
- Railsを勉強した内容のアウトプット
- Railsを勉強していく中でマイグレーションの仕組みを理解していなかったため自分用のメモ

# マイグレーションとは?
- テーブルレイアウトを作成・変更するための仕組み
- SQLを書くことなくテーブルの作成やカラムを追加したりすることができる

## なぜSQLを書く必要がないのか
- ActiveRecordがマイグレーションファイルに書かれたい内容をSQLに翻訳(?)し実行する

## 処理のイメージ
![スクリーンショット 2019-03-24 20.27.21.png](https://qiita-image-store.s3.amazonaws.com/0/179132/37cdc42d-38d3-2013-f6c0-3d5c143328ea.png)

- schemaテーブルには実行ずみのマイグレーションをタイムスタンプで管理している
    - 実行ずみのマイグレーションファイルのタイムスタンプが記録
- railsコマンドの`db:migrate`で見実行のマイグレーションファイルを自動的に認識し処理を実行


# マイグレーションファイルについて
## マイグレーションファイルとは?
- テーブルを作る際のDBの設計書
- マイグレーションファイルの内容に基づいてテーブルが作成される

## マイグレーションファイルの作成
- Model作成と同時に行う場合とマイグレーションファイル単体で作成する場合がある
    - 新規にテーブルを作成する際にはmodel作成と一緒に行う
    - すでに存在するテーブルに対してレイアウトの修正を行う場合はマイグレーションファイル単体を作成する
    

### model作成時にマイグレーションファイルを作成

```shell:model作成と一緒に作成
rails generate model book isbn:string title:string price:integer publish:string published:date dl:boolean
```

### 既存のテーブルに対して変更を加えるマイグレーションファイルを作成
- `行う処理クラス名`で記述する

```shell:マイグレーションファイル単体
rails generate migration AddColumnBooks
```
- Modelと一緒に作成される例しか見たことないけどマイグレーションファイルのみ作成する場合もある

##　マイグレーションファイルの中身

```ruby:
class CreateBooks < ActiveRecord::Migration[5.2]
  def change
    create_table :books do |t|
      t.string :isbn
      t.string :title
      t.integer :price
      t.string :publish
      t.date :published
      t.boolean :dl

      t.timestamps
    end
  end
end
```
- AcativeRecord::Migraionを継承する
- changeメソッドでスキーマの操作を定義している

### create_tebleメソッド

```ruby
   create_table :books do |t|
      t.string :isbn
      t.string :title
      t.integer :price
      t.string :publish
      t.date :published
      t.boolean :dl

      t.timestamps
    end
```

- SQLのCREATE TABLE命令になる
- t.[データ型]でテーブルに属するフィールドを定義
- 主キーはデフォルトでidが自動生成される

### t.[データ型]で定義できるデータ型
| マイグレーションファイルの記述(t.[データ型]) | SQLite|
|:-:|:-:|
| integer  | INTEGER  |   
| decimal  | DECIMAL  |   
| float  | FLOAT  |   
| string  | VARCHAR(256)  |   
| text  | TEXT  |   
| binary  | BLOB  |   
| date  | DATE  |   
| datetime  | DATETIME  |   
| timestamp  | DATETIME   |
| time | TIME|
|boolean| BOOLEAN|

### 列制約の定義
- カラムに入力されるデータに対して制約を与えることができる
- 制約名:値の形で定義できる

```ruby:制約の例
class CreateBooks < ActiveRecord::Migration[5.2]
  def change
    create_table :books do |t|
      t.string :isbn, limit:17, null:false
      t.string :title, limit:100, null:false
      t.integer :price, precision:5, scale: 0
      t.string :publishm, limit:20, default: 'BOOKS!!'
      t.date :published
      t.boolean :dl

      t.timestamps
    end
  end
end
```

## マイグレーションの実行
```shell:マイグレーション実行コマンド
[vagrant@default railsbook]$ rails db:migrate
```
- コマンドを実行するとマイグレーションファイルに基づいてテーブルが作成(更新)される
- postgresの場合のマイグレーション実行後

## マイグレーション実行後のスキーマ
- created_atとupdated_atは自動的に付与される
    - 生成された時のタイムスタンプとデータが更新された時のタイムスタンプ

```shell:マイグレーション実行後のテーブルスキーマ
railsbook_development=# \d books
                                     Table "public.books"
   Column   |            Type             |                     Modifiers
------------+-----------------------------+----------------------------------------------------
 id         | bigint                      | not null default nextval('books_id_seq'::regclass)
 isbn       | character varying           |
 title      | character varying           |
 price      | integer                     |
 publish    | character varying           |
 published  | date                        |
 dl         | boolean                     |
 created_at | timestamp without time zone | not null
 updated_at | timestamp without time zone | not null
Indexes:
    "books_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "reviews" CONSTRAINT "fk_rails_924a0b30ca" FOREIGN KEY (book_id) REFERENCES books(id)
```
#まとめ
- マイグレーションファイルに記述された内容に基づいてActiveRecordがSQLに翻訳してテーブルの作成と更新を行う
- migrationファイルにはカラムの定義が記述されている

# 所感
- 今までの経験では直接DBにアクセスしてテーブルを作っていたためマイグレーション機能の便利さに感動した
- ただしSQLの知識が必要であることに違いはないため、もっと勉強をしていきたい