【Rails】バリデーションを実装する

[シンプルなTODOアプリ](https://qiita.com/d0ne1s/items/5e63dde992f20f25b8bb)にバリデーション（入力制限）を追加していきます。

バリデーションは`create`、`save`、`update`などのメソッドが呼び出されたタイミングで実行されます。

##バリデーションを追加する
タスクの最大文字数を20文字に設定するバリデーションをmodelに記述します。
文法は`validates :{カラム名}, {ルール名}: {ルールの内容}`です。

```/app/models/task.rb
class Task < ApplicationRecord
  validates :title, length: {maximum: 20}
end
```

##エラーメッセージを表示する
バリデーションに失敗するとfalseが返され、`@{オブジェクト名}.errors.full_messages`でエラーメッセージの配列を取得することができます。
まずはControllerを修正し、エラーが発生した場合時にトップページに移動しないようにします。

```/app/controllers/tasks_controller.rb
class TasksController < ApplicationController
.
.
  def create
    @task = Task.new(task_params)
    if @task.save
      redirect_to tasks_url
    else
      render 'tasks/new'
    end
  end
.
.
  def update
    @task = Task.find(params[:id])
    if @task.update(task_params)
      redirect_to tasks_url
    else
      render 'tasks/edit'
    end
  end
.
.
end
```

次に、Viewファイルにエラーメッセージを表示する記述を追加します。

```erb:/app/views/tasks/new.html.erb
<h1>新規タスク</h1>
<% if @task.errors.any? %>
  <div>
    <ul style="color: red">
      <% @task.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>
<%= form_for(@task) do |f| %>
・
・
```
```erb:/app/views/tasks/edit.html.erb
<h1>タスク編集</h1>
<% if @task.errors.any? %>
  <div>
    <ul style="color: red">
      <% @task.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>
<%= form_for(@task) do |f| %>
・
・
・
```
##エラーメッセージを日本語化する
デフォルトのエラーメッセージは英語です。`rails-i18n`というgemを使って日本語化します。まずはgemを追加しましょう。

```ruby:gemfile
gem 'rails-i18n'
```
```terminal
$ bundle install
```
次に`/config/application.rb`に以下の記述を追加します。

```/config/application.rb
.
.
module BoardApp
  class Application < Rails::Application
.
.
    config.i18n.default_locale = :ja
  end
end
```
<img width="503" alt=" 2019-11-21 18.15.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244893/72256589-32a6-295f-6bcf-d24edce99521.png">
modelの属性名が英語のままなので、日本語に変更しましょう。`config/locales/ja.yml`というファイルを作成し、以下のようにカラム名と日本語の対応表を記述します。

```config/locales/ja.yml
ja:
  activerecord:
    models:
      task:           #model名
    attributes:
      task:           #model名
        title: タスク名 #カラム名
```
作成したファイルへのパスを通します。

```/config/application.rb
.
.
config.i18n.default_locale = :ja
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.yml').to_s]
.
.
```
<img width="503" alt=" 2019-11-21 18.39.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244893/10195d5a-a826-1500-f3c8-b1681851ef21.png">
日本語で表示されました。

##よく使うバリデーション一覧
・最大文字数：`length: { maximum: 20 }`
・最小文字数：`length: { minimum: 20 }`
・文字数の範囲：`length: { in: 1..30 }`
・空でない：`presence: true`
・他と被っていない：`uniqueness: true`
・正規表現：`format: { with: /<正規表現>/}`
・「<属性名>_confirmation」と一致：`confirmation: true`

##複数指定する場合
複数指定する場合、ルールをカンマで区切ります。

```ruby:/app/models/task.rb
class Task < ApplicationRecord
  validates :title, length: {maximum: 20}, presence: true, uniqueness: true
end
```

メールアドレスの入力制限

```ruby:model
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, uniqueness: true, format: { with: VALID_EMAIL_REGEX }
```
##参考
・[Railsのバリデーションエラーのメッセージの日本語化](https://qiita.com/Ushinji/items/242bfba84df7a5a67d5b)
・[Railsバリデーションまとめ](https://qiita.com/h1kita/items/772b81a1cc066e67930e)