【Rails】初めてのDB設計

# SQL（Structured Query Language）とは
- リレーショナルDB（RDB）に命令を行う言語。
- ISO（国際標準化機構）で規格化されており、どんなリレーショナルDBにも、同じ文法で操作する。 
- **リレーショナルDB（RDB）**: Webアプリで一般的に使用される、表形式でデータ管理するDBのこと。（例：MySQL、PostgreSQL、SQliteなど）
- 命令は2つに分類。  
**・** 定義： `DDL`（Data Definition Language）  
**・** 操作： `DML`（Data Manipulation Language）

**【DDLの命令】**

|命令|機能|
|:--|:--|
|CREATE|DB、テーブル作成|
|ALTER|DB、テーブル更新|
|DROP|DB、テーブル削除|

**【DMLの命令】**

|命令|機能|
|:--|:--|
|INSERT|データ登録|
|UPDATE|データ更新|
|DELETE|データ削除|
|SELECT|データ検索|

## ターミナルでのSQL文実行
- SQLの実行には、DBへの接続が必要なので、以下のコマンドで`mysql`に**rootユーザー**で接続すると、MySQLが起動し、SQL文でMySQLが操作できる。

```sql:ターミナルでのSQL操作
-- mysqlに接続
 % mysql -u root

-- 今まで作ったDBの一覧表示
 mysql> SHOW DATABASES;

-- DB作成
 mysql> CREATE DATABASE DB名;

-- DBを選択
 mysql> USE DB名;

-- DB内のテーブル一覧表示
 mysql> SHOW TABLES;

-- テーブル作成
 mysql> CREATE TABLE テーブル名 (カラム名 カラム名の型, ……);
 mysql> CREATE TABLE items (id INT, name VARCHAR(255));
  -- ※ rails g model モデル名 でテーブルに紐づくモデルとマイグレーションファイルを作成/実行(rake db:migrate)するのと同義。
  -- ※ rake db:migrate で、 CREATE TABLE というSQL文が動いてる

-- テーブル構造(カラム名、カラム型、制約など)の確認
 mysql> SHOW columns FROM テーブル名;
 mysql> SHOW columns FROM items;

-- テーブル構造の変更(カラムの追加・修正・削除など)
 mysql> ALTER TABLE テーブル名 操作
 -- カラム追加
  mysql> ALTER TABLE テーブル名 ADD カラム名 カラム型;  -- 1つ追加
  mysql> ALTER TABLE テーブル名 ADD (カラム名 カラム型, ……);  -- 複数追加
  mysql> ALTER TABLE items ADD (price int, zaiko int);
 -- カラムの修正 （カラム型は変更がなくても、書く必要がある！）
  mysql> ALTER TABLE テーブル名 CHANGE 古いカラム名 新しいカラム名 新しいカラム型;
  mysql> ALTER TABLE items CHANGE zaiko stock int;
 -- カラムの削除
  mysql> ALTER TABLE テーブル名 DROP カラム名;
  mysql> ALTER TABLE items DROP stock;


 -- データの登録
  -- 全カラムに値を入れる場合
   mysql> INSERT INTO テーブル名 VALUES(値1, ...);
  -- 特定カラムのみに値を入れる場合 （指定しないカラムはデフォルト値(NULL)が入る）
   mysql> INSERT INTO テーブル名(カラム名1, ...) VALUES(値1, ...);  
   mysql> INSERT INTO items VALUES(1, "ペン", 120);
   mysql> INSERT INTO items(id, name) VALUES(2, "消しゴム");

 -- テーブルの全レコード表示
  mysql> SELECT * FROM items;

 -- データ更新
  mysql> UPDATE テーブル名 SET 変更内容 WHERE 条件;
  mysql> UPDATE items SET price = 100 WHERE id = 2;

 -- データ削除
  mysql> DELETE FROM テーブル名 WHERE 条件;
  mysql> DELETE FROM items WHERE id = 2;

-- mysqlを終了
 mysql> exit
```

|SQL文|機能|
|:---:|:--:|
|SHOW DATABASES 文|DB一覧表示|
|CREATE DATABASE 文|DB作成|
|CREATE TABLE 文|テーブル作成|
|USE 文|DBを選択|
|USHOW TABLES文|DB内のテーブル一覧表示|
|ALTER TABLE 文|カラムの追加・修正・削除|
|INSERT 文|テーブルにデータ登録|
|UPDATE 文|テーブルのデータ更新|
|DELETE 文|テーブルのデータ削除|

- SQL文の終わりは `;`を付ける。  
(忘れたら、SQLがまだ続くとみなされ、`->` が表示されるので、`;`を入力すればOK)。
- カラム型の(例) `INT`：数字、`VARCHAR(●)`：最大●文字の文字列


## クエリでのSQL文実行
- **検索**では、クエリから実行する。理由は、
 1. 検索では、SQL文が長くなるので、タイプミス時の修正が容易
 2. 検索結果の出力も長くなっても、SQL文が流れず、見やすい
 3. SQL文の文末の `;`が不要。

- クエリ(例えば、SequelPro)でのSQL文の実行方法は、上画面にSQL文を書き、`現在を実行`をクリックすると実行される。
- `SELECT句`(テーブルの指定) ＋ `FROM句`(取得するカラムの指定)が、検索の基本構造。
- `WHERE句`： 取得するレコードを制限。条件式は、
**比較演算子**(<、>、..)、
**AND演算子**(and、or)、
**BETWEEN演算子**(上限と下限の指定)、
**IN演算子**(1つのカラムにリストを指定し、値がリストに含まれる時 true)、
**NOT演算子**など。
- `ワイルドカード` : 文字の代わりに使える記号のこと。`*`は全部の意味。

```sql:クエリでの検索
-- SQL文のコメントアウト

-- 検索の基本構造
 SELECT カラム名  -- 取得カラムの指定
 FROM テーブル名  -- 検索するテーブルの指定
 WHERE 条件     -- 取得レコードの制限
 -- (例)全カラムを取得、レコードの検索条件を指定
  SELECT *
  FROM users
  WHERE age <= 22 AND prefecture = "神奈川県"
 -- (例)
  SELECT *
  FROM users
  WHERE age <= 20 OR prefecture = "東京都"
 -- (例)
  SELECT *
  FROM users
  WHERE age BETWEEN 21 AND 24
 -- (例)
  SELECT *
  FROM users
  WHERE NOT prefecture = "東京都"
 -- (例)
  SELECT *
  FROM users
  WHERE prefecture IN ("東京都", "神奈川県")

-- 検索データの結合
 CONCAT(文字列1, 文字列2, ..) -- 文字列の連結
 -- (例)フルネームを出力する場合(通常、カラム名はSQL文になる)
  SELECT CONCAT(family_name, first_name)
  FROM users
 -- (例)フルネームを出力する場合(カラムに別名を付ける場合)
  SELECT CONCAT(family_name, first_name) AS "名前"  -- AS は省略可
  FROM users

-- 重複する行の除外
 SELECT DISTINCT カラム名
 -- (例)shiftsテーブルから、date = "2015-07-01"のカラム取得(重複するuser_idを除く)
  SELECT DISTINCT user_id
  FROM shifts
  WHERE date = "2015-07-01"

-- レコードのグループ化
 GROUP BY カラム名
 -- (例)shiftsテーブルからdate="2015-07-01"に誰がシフトに入ったかを取得("user_id"が同じものをグループ化し、"user_id"表示)
  SELECT user_id
  FROM shifts
  WHERE date = "2015-07-01"
  GROUP BY user_id

-- レコード数を数える
 SELECT COUNT(カラム名)
 SELECT COUNT(*)  -- 全部の値がNULLのレコードも含めた行数を取得
 -- (例)shiftsテーブルからdate="2015-07-01"に、誰が、何コマずつシフトに入ったかを取得(カラムにコマ数という別名を付ける)
  SELECT
    user_id,
    COUNT(*) "コマ数"
  FROM shifts
  WHERE date = "2015-07-01"
  GROUP BY user_id

-- テーブルの結合(テーブル1にテーブル2を結合(条件：テーブル1のカラム1がテーブル2のカラム2と一致するもの))
 FROM テーブル名1
 JOIN テーブル名2 ON テーブル名1.カラム名1 = テーブル名2.カラム名2
 -- (例)shiftsテーブルにusersテーブルを結合。(shiftsテーブルの"user_id"がusersテーブルの"id"と一致する行を結合)
  FROM shifts
  JOIN users ON shifts.user_id = users.id
 -- ↑は普通、簡略して書く！(テーブルに別名で扱う。テーブル名の頭文字が一般的。)
  FROM shifts s
  JOIN users u ON s.user_id = u.id
 -- まとめて書くと、
  SELECT
    CONCAT(family_name, first_name) "名前",
    COUNT(*) "コマ数"
  FROM shifts s
  JOIN users u ON s.user_id = u.id
  WHERE date = "2015-07-01"
  GROUP BY user_id

-- サブクエリ：検索結果を用いた検索(例えば、↑の検索に該当しないデータの取得とか)
 SELECT *
 FROM users
 WHERE id NOT IN (
   SELECT DISTINCT user_id
   FROM shifts
   WHERE date = "2015-07-01"
 )
```
```sql:IN演算子(カラム名に値1、もしくは、値2、...を含む場合true)
-- (値1, 値2, ……)部分がリスト
 WHERE カラム名 IN (値1, 値2, ……)
-- ↑と同義
 WHERE カラム名 = "値1" OR カラム名 = "値2" OR ...
```

- `CONCAT` 関数: 複数の文字列を連結する関数(※文字列に**NULL**があれば、結果は**NULL**)。
- `AS` 句: `CONCAT` 関数での検索結果のカラム名は、SQL文のままで見にくいので、検索結果のカラム名の変更する時に使う。
- `DISTINCT` キーワード: 指定カラムの値が重複する行を除外して取得。
- `GROUP BY` 句: 指定カラムが同じ値のデータをグループにまとめる(表示されないデータもそのグループに保持されてる)。  
`DISTINCT`と似てるが、`GROUP BY`は、**グループ単位で集計した結果を取得できる**ことが利点。
- `COUNT` 関数: グループ化したデータに使える集計関数。カラムを指定して使用することで、値が**NULLでない**行数を取得できる。  
`GROUP BY`句を併用すると、各グループが持つレコードの数を取得できる
(※ グループ化データに使える**集計関数**は、他に、平均`AVG`、最大値`MAX`、最小値`MIN`など)。
- `JOIN` 句: 指定テーブルの、カラムが同じデータを結合。FROM句の後に書き、結合する対象テーブルを指定。`JOIN`には`INNER JOIN`、`LEFT JOIN`や`RIGHT JOIN`など、結合法則の違うものがある。
- `サブクエリ`: 検索結果を使って、別のSQL文を実行する仕組みのこと。`WHERE`句で使うことが多いが、`SELECT`句や`FROM`句でも使える。







# DBとは
- DB構成要素:3つ(サービスで扱う概念（エンティティ）、エンティティの属性、エンティティ間の関係性（リレーション）)。
**・** `エンティティ`: サービスで管理する必要のある概念(情報、データ)のこと。**テーブル**にあたる。(例: ユーザー、投稿内容、コメント)
**・** `エンティティの属性`: エンティティが持つ個別情報のこと。**カラム**にあたる。(例: タイトル、説明、公開日、監督)
**・** `リレーション`: エンティティ間の関係性のこと。(例：映画-を監督)

- 属性の中には`キー`(テーブル内のレコード同士を識別するための被らないデータ)が存在する。 主キー 、 外部キー の2種類ある。
**・** `主キー`: テーブル内のレコードを判別のための識別子カラム(多くの場合、**id**)。
**・** `外部キー`: 関連する他のテーブルの主キー(カラム)と関係がある時に必要なカラム。他のテーブルのレコードとのリレーションを表すために使う。

## DB設計
- サービスに必要な情報の管理方法を決める作業。
- **【DB設計の手順】**
 1. 必要な機能を洗い出す。(ページの繋がりを把握から考えてみる)
 2. 洗い出した機能に、管理したいエンティティ(必要なデータ)を抽出する。
 3. データの持つ属性を決める。テーブルの分け方も考える。  
※ データ変更・削除しないテーブルは、active_hashかenumを使えないか？も考えてみる。
 4. テーブルの繋がり(リレーション)を決める(ER図)。  
**ER図とは？** ： Entity-Relationship Diagramの略、テーブル間の関係を視覚的に表した図（IE表記法 で書く）。



## テーブル作成
モデル ＋ マイグレーションファイルを作成

```rb:テーブル作成
$ rails g model モデル名
```

## テーブル変更
マイグレーションファイルのみ作成。※ 名前は何でもok。

```rb:テーブル変更
$ rails g migration マイグレーション名
 $ rails g migration DropUser
# カラム追加
 $ rails g migration Addカラム名Toテーブル名 カラム名:型
 $ rails g migration AddNameToUsers name:string
# カラム削除
 $ rails g migration Removeカラム名Fromテーブル名 カラム名:型
# カラム名変更
 $ rails g migration RenameFrom変更前のカラム名To変更後のカラム名Onテーブル名
# カラムの Null制約変更
 $ rails g migration ChangeColumnToNotNull
# カラム変更
 $ rails g migration ChangeColumnToUser
# 外部キー削除
 $ rails g migration AddArticleToUsers article:references

# テーブル作成時に外部キーをreferences型カラムで保存
 $ rails g model モデル名(大文字単数) カラム名:references
 $ rails g model UserAccount user:references # 外部キー作成

$ rails g model User uuid:string:unique name:string
```

## マイグレーションの実行・確認・取下げ・編集・削除

```rb:マイグレーション実行
$ rails db:migrate  # rails4までは、rakeコマンド
```

```rb:マイグレーションの確認
$ rails db:migrate:status
 → up：実行済み、down:実行前の状態
```
※ schema_migrationsテーブルにもマイグレーションファイルのバージョンが保存されている(version：××××××)。
※ スキーマファイル(schema.rb)：最新のテーブル一覧が記録されている。

```rb:実行済みのマイグレーション取下げ
$ rails db:rollback
 up → downの状態になる。
# 新しいものから2つのファイルを同時にロールバック
 $ rails db:rollback STEP=2
```
※ upの状態でマイグレーションファイル削除すると、エラーに繋がるので、down状態を確認してから削除！


```rb:マイグレーションをリセットして再実行(変更済みのマイグレーションを変更・削除するときとか。。)
# DBを削除後に、db/migrate/**.rb を古い順から実行
 % rails db:migrate:reset

# マイグレーションファイルの順番に問題がある場合、NGになることがある。
# そんな時は、分けて実行すると行ける場合がある。
 % rails db:reset   # db/schema.rbを元にDB作成
 % rails db:migrate
```

```ruby:マイグレーションファイルの編集(テーブル作成)
def change
  create_table :hoges do |t|
    t.カラムの型   :カラム名
    t.string     :name
    t.text       :text
    t.references :user, index: true, foreign_key: true
    t.timestamps
  end
end
```
```ruby:マイグレーションファイルの編集(カラム追加)
def change
  # カラム追加
  add_column    :テーブル名, :カラム名, :型
  # カラム削除
  remove_column :テーブル名, :カラム名, :型
  remove_columns :テーブル名, :カラム名, :カラム名,  :カラム名
  # カラム名変更
  rename_column :テーブル名, :変更前のカラム名, :変更後のカラム名
  # カラムの制約、オプションを変更
  change_column :テーブル名, :カラム名, :型
  change_column :users, :name, :string, null: false
  change_column :users, :name, :string, limit: 10
  change_column :users, :uuid, :string, null: false, default: 0
  change_column :テーブル名, :カラム名, :型, null: true  # NULL制約
  change_column :テーブル名, :カラム名, :型, null: false  # NOT NULL制約
  change_column :テーブル名, :カラム名, :型, index: true  # インデックス
  change_column :テーブル名, :カラム名, :型, default: "piyo"  # デフォルト
  change_column :テーブル名, :カラム名, :string, limit: 12  # 長さ varchar(12)
  change_column :テーブル名, :カラム名, comment: "コメントです"  # コメント
  # テーブル作成
  create_table :テーブル名
  drop_table   :テーブル名
  # テーブル名変更
  rename_table  :現在のテーブル名,  :新しいテーブル名
  # インデックスをつける
  add_index  :テーブル名,  :インデックスを付けるカラム名 [, オプション])
  add_index :company, :company_name
  add_index :users, [:name, :name2]
  add_index :user_accounts, [:provider, :uid], :name => 'unique_provider_uid', :unique => true
  # インデックスを削除
  remove_index :テーブル名, :カラム名
  remove_index :company, name: :company_name_fk
  # 外部キーを追加
  add_reference  :テーブル名,  :リファレンス名 [, オプション]
  add_reference  :hoges,  :user, foreign_key: true
  add_reference :テーブ名, :カラム名, index: true

  add_foreign_key :対象テーブル, :指定先テーブル, :column :対象のカラム名
  add_foreign_key  :テーブル名,  :指定先のテーブル名 [, オプション]
  add_foreign_key :対象のテーブル, :指定先のテーブル, name: :foreign_keyの別名
  add_foreign_key :companies, :accounts
  add_foreign_key :companies, :accounts,  name: :huga_id  # 別名をつける場合
  add_foreign_key  :trades,  :users, column: :seller_id  # seller_idカラム対して外部キー制約をつける場合
  # 外部キーを削除
  remove_foreign_key  :テーブル名,  :指定先のテーブル名
  remove_foreign_key :users, column: :article_id  # 外部キー削除
  remove_reference :users, :article, foreign_key: true  # カラムも一緒に削除する場合
end
```
※ **Rails5**では、デフォルトでidは`bigint`で、参照元テーブルのカラムをintegerで作成すると`foreign key`が作成できない。なので、テーブルのカラムを`bigint`で作成して、外部キーを設定すると良さそう！！

## マイグレーションファイルでよく使うメソッド
|メソッド名|概要|
|:-----|:----|
|add_column|カラム追加|
|remove_column|カラム削除|
|remove_columns|複数カラムを削除|
|rename_column|カラム名変更|
|change_column|カラムの情報変更|
|create_table|テーブル作成|
|drop_table|テーブル削除|
|rename_table|テーブル名変更|
|add_index|インデックス追加|
|remove_index|インデックス削除|
|add_reference|外部キー作成|
|remove_reference|外部キー削除|
|add_foreign_key|外部キー制約付与|
|remove_foreign_key|外部キー制約削除|

## カラムの型
|カラム型|概要|
|:-----|:----|
|string|文字（〜255文字）|
|text|文字（255文字〜）|
|integer|通常の整数|
|smallint|狭範囲の整数|
|bigint|大きな整数|
|float|小数点を含む数|
|decimal, numeric|大きな数 ※桁数などを指定する時|
|boolean|真/偽|
|time|時刻 12:00:00|
|date|日付 2020-01-01|
|datetime|日時 2001-01-01 01:01:00|
|timestamp|タイムスタンプ|
|json|JSONで保存|
|binary|画像などをバイナリデータにしたい時|
|references|外部キー|

## 制約
特定のデータを保存さないためのバリデーション。

|制約の種類|記述|概要|
|:------:|:--:|:--|
|NOT NULL制約|null: false|カラムに設定する制約。NULL（空）では保存さない（エラーにする）。必須項目に使う。|
|一意性制約|unique: true|カラムに設定する制約。テーブル内で重複データの保存を禁止する|
|主キー制約|-|フォーマットで設定。主キーの属性値が存在し、かつ、重複しないことを保証する。`主キーへの NOT NULL制約 + 一意性制約`と同義。|
|外部キー制約|foreign_key: true|外部キーに対応するレコードが存在することを保証する|
|外部キーのnilを許可|optional: true|外部キーが空でも保存を可能にする|
**※ 外部キーのカラム名を指定したい時**
 
```ruby:モデル
 belongs_to :user, foreign_key: :seller_id
```

## インデックス
- DBの機能の1つで、テーブル内のデータの**検索**速度向上のための仕組み。索引(目次)のイメージ。
- 検索に使うカラムに使う。
- インデックスを貼るメリット： **データの読み込み/取得速度向上**  
(牽引で目的の場所を見つけ、データを読み取るため)
- インデックスを貼るデメリット: **DBの容量が圧迫される**のと、**書き込み速度低下**  
(インデックスは、テーブルのデータとは別の領域に保存されるので、データを書き込む時(保存/更新)、テーブルへの書き込み、インデックスへの書き込みが必要なため)
- 複数カラムにインデックスを貼れるが、カラム単体で検索する時は、検索速度は向上しないので、**その複数カラムのセットでめっちゃ検索する場合だけ、複数カラムにインデックスを貼る**。

```rb:マイグレーションファイル
def change
  add_index :テーブル名, :カラム名
end
```

## 正規化
- DBのデータ構造を無駄のないシンプルな構造にする手順。
- 正規化後のDB構造を`正規形`、正規化していないDB構造を`非正規形`という。
- 正規化順番: 非正規形 → 第1正規形 → 第2正規形 → 第3正規形 → ボイスコッド正規形 → 第4正規形 → 第5正規形。(第4正規形以降は、パフォーマンス低下の可能性があり、第三正規形に留めるのが一般的。)
- 正規化のデメリット： 正規化は進めるほどに、パフォーマンスが低下する。小さなテーブルが増えていくことが理由。関連テーブルの検索のたびにSQL実行回数が増え、速度低下するため、第3正規形で終えることが多い。

**【テーブルの問題点】**
**・** 重複するカラム：冗長なDBになる。
**・** 1つのテーブルに複数の情報(エンティティ)が混在：可読性を含め、パフォーマンスが低下。
この問題を解決するのが`正規化`。

#### 正規化の順番
- **第1正規形**： 同一カラムが存在しない、かつ、レコードを構成する1つのマスに、値が1つずつ入る状態にすること。
- **第3正規形**： 第2、第３正規形は似ており、違いは複雑な概念のため、第2正規形は割愛。第3正規形は、主キーに依存、かつ、非キー属性（主キーでないもの）同士の依存がない状態にすること。
- 混在したエンティティは、属性ごとにテーブルを分ける。



## N+1 問題
モデルでDBへアクセス時、SQLが発行される。アソシエーションで、子モデルのインスタンスを複数取得する時は、`N+1問題`を考慮し、`includes`メソッドなどで解消する！










## モデルでアソシエーション定義
- 1 対 多: `has_many :複数` 対 `belongs_to :単数` 
- 1 対 1: `belongs_to :単数`。所有（まるごと含む）場合は、`has_one :単数`。
- 多 対 多： 中間テーブルを作成。`has_many through` オプション↓↓

```rb:多対多モデル
has_many :相手のテーブル名, through: :中間テーブル名

# 中間テーブル
belongs_to :テーブル名1
belongs_to :テーブル名2


# アソシエーション定義すると、自動で以下のメソッドが使えるようになる。
 # 通常のレコード作成
 変数名1 = モデル名1.create(カラム名: "値", ..)  # 単体のインスタンス生成
 変数名2 = モデル名2.create(カラム名: "値", ..)
 # 多対多を定義したレコード作成
 変数名1.相手テーブル名2(複数形).create(カラム名: "値", ..)    # 多対多の関係を使って、変数名1に関係する相手テーブル名2のインスタンス生成
 # リレーション追加
 変数名1.相手テーブル名2(複数形) << 変数名2   # 後からインスタンス同士を関連付けも可能
 # 変数名1と関係する相手テーブル名2の配列に、モデル名1のインスタンス追加でリレーション生成。

 # リレーションを利用したレコード取得
 変数名.相手テーブル名(複数形)  # リレーションしている要素を全て出力(返り値は、関連付けられているインスタンスが出力される)
```










## モデルでバリデーション定義
- [公式ドキュメント](https://railsdoc.com/validation)
- バリデーションを自分で定義することもできる。

```rb:モデル(詳細は、公式ドキュメントを参照)
# 汎用的に使うバリデーション
validates(フィールド名, 種類 [, オプション])
  validates :form, acceptance: true   # チェックボックスがオン？
  validates :form, acceptance: false  # チェックボックスがオフ？
  validates :email, confirmation: true  # テキストフィールドが一致するか？
  validates :email, confirmation: false  # テキストフィールドが一致しないか？
  validates :subdomain, exclusion: {in: %w(www us ca jp)}   # 含まないか?
  validates :legacy_code, format: {with: /\A[a-zA-Z]+\z/}   # 正規表現と一致するか?
  validates :size, inclusion: {in: %w(small medium large)}     #  含むか?
  validates :name, length: {minimum: 2}   # 長さ
  validates :points, numericality: true   # 数値のみか
  validates :name, :login, :email, presence: true   # 空で無いか？
  validates :name, :login, :email, absence: true   # 空か？
  validates :email, uniqueness: true   # 重複してないか？

# 一意
validates_uniqueness_of(フィールド名 [, オプション])

# 関連付けたモデルもバリデーション（関連が無い場合はバリデーションは成功）
validates_associated(対象 [, ...])

# 空でないか
validates_presence_of(対象 [, ...])
# 空であるか
validates_absence_of(フィールド名 [, ...])
# チェックボックスにチェックが入っているか
validates_acceptance_of(フィールド名 [, ...])

# 2つのフィールドが等しいか
validates_confirmation_of(フィールド名 [, ...])

# 値が配列・範囲に含まれてないか
validates_exclusion_of(フィールド名 [, ...])
# 値が配列・範囲に含まれるか
validates_inclusion_of(フィールド名 [, ...])

# 正規表現パターンに一致するか
validates_format_of(フィールド名 [, ...])

# 文字列の長さ
validates_length_of(フィールド名 [, ...])

# 数値の大小、型
validates_numericality_of(フィールド名 [, ...])

# バリデーションの別クラスにレコードを渡し、複雑な条件のエラーを追加
validates_with(引数)

# ブロックに対してのバリデーション
validates_each(キー名, [,  オプション])

```
### バリデーションの種類

|validates の種類 |概要|
|:--|:--|
|:acceptance|チェックボックス入力|
|:confirmation|テキストフィールドが一致するか|
|:exclusion|含まないか|
|:format|正規表現と一致するか|
|:inclusion|含むか|
|:length|長さ|
|:numericality|数値のみか|
|:presence|空で無いか|
|:absence|空か|
|:uniqueness|重複|

### バリデーションのオプション

|オプション|概要|
|:--|:--|
|:message|失敗時の表示メッセージ|
|:scope|一意性制約したい他のカラム|
|:conditions|検索条件|
|:case_sensitive|大/小文字の区別、(デフォルト true)|
|:on|実行タイミング、(デフォルト 保存時)|
|:allow_nil|nilをスキップ、(デフォルト false)|
|:allow_blank|nil、空文字をスキップ、(デフォルト false)|
|:if|バリデーション条件|
|:unless|バリデーションしない条件|
|:strict|失敗時の例外処理|
|:with|正規表現パターン|
|:without|正規表現パターン|
|:multiline|行の先頭 or 末尾|
|:within|比較する配列、範囲|


### 長さに関するオプション

|オプション|概要|
|:--|:--|
|:minimum|最小値|
|:maximum|最大値|
|:in、　:within|範囲内か|
|:is|等しいか？|
|:too_long|:maximum違反時のエラーメッセージ|
|:too_short|:minimum違反時のエラーメッセージ|
|:wrong_length|:is違反時のエラーメッセージ|
|:tokenizer|文字列の分割方法|	 

### 数値、型に関するオプション

|オプション|概要|
|:--|:--|
|:only_integer|整数か|
|:greater_than|指定値より大きいか|
|:greater_than_or_equal_to|指定値以上か|
|:equal_to|指定値と等しいか|
|:less_than|指定値より小さいか|
|:less_than_or_equal_to|指定値以下か|
|:other_than|指定値以外か|
|:odd|奇数か|
|:even|偶数か|