ウィザード形式の登録フォームでバリデーション

この記事は、以下の記事の続きです。
『Railsウィザード形式フォームで新規登録〜Devise+session〜』
https://qiita.com/ATORA1992/items/40fc543742a6df5a17c1

#やりたいこと
ウィザード形式のフォームで、画面遷移するたびにバリデーションをかけたい。

#実装方法
1. modelにvalidatesを記述する
2. 遷移するたびに、before_actionを呼びだす
3. before_action内で、仮のインスタンスを作成し、バリデーションを確認する

これの繰り返しで、やりたいことを実現できます。

#具体例(抜粋）
```user.rb
　VALID_EMAIL_REGEX =                 /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  # step1入力項目
  validates :nickname,                presence: true, length: {maximum: 20}
  validates :email,                   presence: true, uniqueness: true, format: { with: VALID_EMAIL_REGEX }
  validates :password,                presence: true, length: {minimum: 6, maximum: 128},on: :save_to_session_before_phone
  validates :password_confirmation,   presence: true, length: {minimum: 6, maximum: 128},on: :save_to_session_before_phone

  # step2入力項目
  validates :last_name,               presence: true
  validates :first_name,              presence: true
  validates :last_name_kana,          presence: true
  validates :first_name_kana,         presence: true
```
入力フォームに必要なバリデーションを該当modelに記述してください。

```signup_controller.rb
class SignupController < ApplicationController
  before_action :validates_step1, only: :step2 # step1のバリデーション
  before_action :validates_step2, only: :step3 # step2のバリデーション

 ~省略~

  # 各アクションごとに新規インスタンスを作成します
  def step1
    @user = User.new # 新規インスタンス作成
  end

  def step2
    @user = User.new # 新規インスタンス作成
  end

  ~省略~

  # before_actionごとに、遷移元のページのデータをsessionに保管していきます
  # 仮でインスタンスを作成しバリデーションチェックを行います
  def validates_step1
    # step1で入力された値をsessionに保存
    session[:nickname] = user_params[:nickname]
    session[:email] = user_params[:email]
    session[:password] = user_params[:password]
    session[:password_confirmation] = user_params[:password_confirmation]
    # バリデーション用に、仮でインスタンスを作成する
    @user = User.new(
      nickname: session[:nickname], # sessionに保存された値をインスタンスに渡す
      email: session[:email],
      password: session[:password],
      password_confirmation: session[:password_confirmation],
      last_name: "山田", # 入力前の情報は、バリデーションに通る値を仮で入れる
      first_name: "太郎", 
      last_name_kana: "ヤマダ", 
      first_name_kana: "タロウ", 
      ~省略~
    )
    # 仮で作成したインスタンスのバリデーションチェックを行う
　　render '/signup/step1' unless @user.valid?
  end

  def validates_step2
    # step2で入力された値をsessionに保存
    session[:last_name] = user_params[:last_name]
    session[:first_name] = user_params[:first_name]
    session[:last_name_kana] = user_params[:last_name_kana]
    session[:first_name_kana] = user_params[:first_name_kana]
    # バリデーション用に、仮でインスタンスを作成する
    @user = User.new(
      nickname: session[:nickname], # sessionに保存された値をインスタンスに渡す
      email: session[:email],
      password: session[:password],
      password_confirmation: session[:password_confirmation],
      last_name: session[:last_name], 
      first_name: session[:first_name], 
      last_name_kana: session[:last_name_kana], 
      first_name_kana: session[:first_name_kana], 
      ~省略~
    )
    # 仮で作成したインスタンスのバリデーションチェックを行う
　　render '/signup/step2' unless @user.valid?
  end 
```
ウィザードフォームを作っているコントローラーで、バリデーションチェックを行います。
各ページに対応するアクションでは、新規インスタンスの作成を行なってください。
次のページに遷移する前（次のページに対応するアクションを動かす前）に*before_action*でバリデーションチェック用のアクションを実行します。

*before_action*のアクションで行うことは、以下の3つです
1. sessionにフォーム情報を保管する
2. バリデーションチェック用の仮インスタンスを作成する
3. 仮インスタンスを元にバリデーションをチェックする（*@user.valid?*)

特に重要なのは、仮のインスタンス作成です。
自分は、インスタンスに必要なカラム情報を全て埋めるようにして実装しました。
なので、sessionで値を保管する前の情報は、バリデーションが通るものを仮置きで記述しています。

フォーム量が増えると、仮置きの情報が増えてしまうので、modelでの*validates*で、以下のように*on: :アクション名*として、バリデーションのかかるアクションを限定する方がいいかもしれません。

```user.rb
　VALID_EMAIL_REGEX =                 /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  # step1入力項目
  validates :nickname,                presence: true, length: {maximum: 20}, on: :validates_step1
  validates :email,                   presence: true, uniqueness: true, format: { with: VALID_EMAIL_REGEX }, on: :validates_step1
  validates :password,                presence: true, length: {minimum: 6, maximum: 128}, on: :validates_step1
  validates :password_confirmation,   presence: true, length: {minimum: 6, maximum: 128}, on: :validates_step1

  # step2入力項目
  validates :last_name,               presence: true, on: :validates_step2
  validates :first_name,              presence: true, on: :validates_step2
  validates :last_name_kana,          presence: true, on: :validates_step2
  validates :first_name_kana,         presence: true, on: :validates_step2
```
```signup_controller.rb
render '/signup/step1' unless @user.valid?(:validates_step1)
render '/signup/step1' unless @user.valid?(:validates_step2)
```

#補足
バリデーションチェックしたあと、エラーメッセージをどうやって取得するか・表示するかは、別記事を参考にしてみてください。
https://qiita.com/ATORA1992/items/218f17deb66c82f27fbc