バリデーションを始めて扱う

# バリデーション（検証）
Active Recordを使って、モデルがデータベースに```書き込まれる前にモデルの状態をバリデーション（検証: validation）```できます。Active Recordにはモデルチェック用のさまざまなメソッドが用意されており、属性が空でないかどうか、属性が一意かどうか、既にデータベースにないかどうか、特定のフォーマットに沿っているかどうか、多岐にわたったバリデーションが行えます。

バリデーションは、```データベースを永続化するうえで極めて重要```です。そのため、save、updateメソッドは、バリデーションに失敗するとfalseを返します。このとき実際のデータベース操作は行われません。上のメソッドにはそれぞれ```破壊的なバージョン (save!、update!) があり、こちらは検証に失敗した場合にさらに厳しい対応```、つまりActiveRecord::RecordInvalid例外を発生します。以下はバリデーションの簡単な例です。

```rb
class User < ApplicationRecord
  validates :name, presence: true
end
irb> user = User.new
irb> user.save
=> false
irb> user.save!
ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
```
### 出典
https://railsguides.jp/active_record_basics.html#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%EF%BC%88%E6%A4%9C%E8%A8%BC%EF%BC%89:~:text=6%20%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%EF%BC%88%E6%A4%9C%E8%A8%BC,can%27t%20be%20blank

### 気づき
バリデーションとsave!やupdate!など例外を発生させるメソッドを組み合わせることで例外処理ができるのか。

# モデルレベルのバリデーションが最適
Railsチームは、ほとんどの場合```モデルレベルのバリデーションが最も適切```であると考えています。
### 出典
https://railsguides.jp/active_record_validations.html#:~:text=Rails%E3%83%81%E3%83%BC%E3%83%A0%E3%81%AF%E3%80%81%E3%81%BB%E3%81%A8%E3%82%93%E3%81%A9%E3%81%AE%E5%A0%B4%E5%90%88%E3%83%A2%E3%83%87%E3%83%AB%E3%83%AC%E3%83%99%E3%83%AB%E3%81%AE%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%8C%E6%9C%80%E3%82%82%E9%81%A9%E5%88%87%E3%81%A7%E3%81%82%E3%82%8B%E3%81%A8%E8%80%83%E3%81%88%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82

### 気づき
大体の場合は、モデルでバリデーションを行うのがいいのか。

#### 関連記事　バリデーションレベルに関して　("モデルレベル rails"で調べた）
https://techracho.bpsinc.jp/hachi8833/2021_12_02/55771#:~:text=1.%20%E3%83%A2%E3%83%87%E3%83%AB%E3%83%AC%E3%83%99%E3%83%AB,%E3%81%97%E3%81%BE%E3%81%86%E3%81%AE%E3%81%A7%E3%81%99%E3%80%82

# 共通のバリデーションオプション
### ```:message```オプション
既に例示したように、:messageオプションを使うことで、```バリデーション失敗時にerrorsコレクションに追加されるカスタムエラーメッセージを指定```できます。このオプションを使わない場合、Active Recordはバリデーションヘルパーごとにデフォルトのエラーメッセージを使います。:messageオプションはStringまたはProcを受け取ります。

Stringの:message```値には、%{value}や%{attribute}や%{model}をオプションで含められます```。これらはバリデーション失敗時に動的に置き換えられます。置き換えにはI18n gemが用いられており、プレースホルダーの文字はこのとおりでなければならず、スペース文字を含めることはできません。

Procの:message値には引数が2つ与えられます。バリデーションの対象となるオブジェクトと、:modelと:attributeと:valueのキーバリューペアを含むハッシュです。
```rb
class Person < ApplicationRecord
  # メッセージを直書きする場合
  validates :name, presence: { message: "省略できません" }

  # 動的な属性値を含むメッセージの場合。%{value}は実際の属性値に
  # 置き換えられる。%{attribute}や%{model}も利用可能。
  validates :age, numericality: { message: "%{value}は誤りかもしれません" }

  # Procの場合
  validates :username,
    uniqueness: {
      # object = バリデーションされる人物のオブジェクト
      # data = { model: "Person", attribute: "Username", value: <username> }
      message: ->(object, data) do
        "#{object.name}さま、#{data[:value]}は既に入力済みです"
      end
    }
end
```
### ```on```オプション
:onオプションは、```バリデーション実行のタイミングを指定```します。ビルトインのバリデーションヘルパーは、デフォルトでは保存時（レコードの作成時および更新時の両方）に実行されます。バリデーションのタイミングを変更したい場合、```on: :createを指定すればレコード新規作成時にのみ```バリデーションが行われ、```on: :updateを指定すればレコードの更新時にのみ```バリデーションが行われます。
```rb
class Person < ApplicationRecord
  # 値が重複していてもemailを更新できる
  validates :email, uniqueness: true, on: :create

  # 新規レコード作成時に、数字でない年齢表現を使える
  validates :age, numericality: true, on: :update

  # デフォルト (作成時と更新時の両方でバリデーションを行なう)
  validates :name, presence: true
end
```

# 例外を表示させる
バリデーションを厳密にし、オブジェクトが無効だった場合に```ActiveModel::StrictValidationFailedが発生する```ようにすることもできます。
```rb
class Person < ApplicationRecord
  validates :name, presence: { strict: true }
end
```
```
irb> Person.new.valid?
ActiveModel::StrictValidationFailed: Name can't be blank
```
### カスタムの例外を表示させることができる。
カスタム例外を```:strictオプションに追加```することもできます。
```rb
class Person < ApplicationRecord
  validates :token, presence: true, uniqueness: true, strict: TokenGenerationException
end
```
```
irb> Person.new.valid?
TokenGenerationException: Token can't be blank
```
### 出典
https://railsguides.jp/active_record_validations.html#:~:text=4%20%E5%8E%B3%E5%AF%86%E3%81%AA%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3,Token%20can%27t%20be%20blank

# 感想
* errorsオブジェクトを使えるようにする。

https://railsguides.jp/active_record_validations.html#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E5%AF%BE%E5%BF%9C%E3%81%99%E3%82%8B:~:text=active%3F%0A%20%20end%0Aend-,7%20%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E5%AF%BE%E5%BF%9C%E3%81%99%E3%82%8B,-valid%3F%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89

* バリデーションをスキップする理由がわかったら使ってみたい。

https://railsguides.jp/active_record_validations.html#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E3%82%B9%E3%82%AD%E3%83%83%E3%83%97:~:text=%E3%82%92%E8%BF%94%E3%81%97%E3%81%BE%E3%81%99%E3%80%82-,1.3%20%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E3%82%B9%E3%82%AD%E3%83%83%E3%83%97,-%E4%BB%A5%E4%B8%8B%E3%81%AE%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89

* procとは?
 
https://railsguides.jp/active_record_validations.html#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A8%E3%83%A9%E3%83%BC%E3%82%92%E3%83%93%E3%83%A5%E3%83%BC%E3%81%A7%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B:~:text=%E3%81%AB%E3%81%AF%E5%80%A4%E3%80%81-,proc,-%E3%81%BE%E3%81%9F%E3%81%AF%E3%82%B7%E3%83%B3%E3%83%9C%E3%83%AB%E3%82%92

まだまだ知らないことばかりだ。
わかったら記事にする。
とりあえずここの技術を実際使ってみて実装する
長さや正規表現なんかも調べることができそうだ。
また勉強しているうちに新しくバリデーションのアイデアが浮かんできそうだ。
javascriptと一緒に使えそうだ。