ユーザー登録時のウィザード形式に変更

## はじめに
オリジナルアプリ制作にあたり、ユーザー登録時に**ウィザード形式**（対話するように順番に操作が進んでいく方式）を用いるように変更しました。
ウィザード形式にすることで、ユーザーからすると見やすく使いやすいとのことだったため、変更することにしました。


変更前はユーザー登録と本人確認が以下の画像のように一緒の画面にある状態。
1ページが縦長になってしまい、少しわかりづらい。（スクショにも全部納まっていないし…。）
なので、今回はユーザー情報登録画面と本人確認登録画面に2ページに分けていきたいと思います。
<img src="https://user-images.githubusercontent.com/72326957/103556288-e5d72100-4ef4-11eb-8712-c50be8ee24a3.png" width=100%>

## 変更前・変更後のテーブルの状態
**変更前**　
現状、会員情報入力と本人確認が同じテーブルになっている。
・Userテーブル

| Column             | Type    | Options     |
| ------------------ | ------- | ----------- |
| nickname           | string  | null: false |
| email              | string  | null: false |
| password           | string  | null: false |
| last_name          | string  | null: false |
| first_name         | string  | null: false |
| last_name_kana     | string  | null: false |
| first_name_kana    | string  | null: false |
| phone_number       | string  | null: false |
<br>

**変更後**　
ウィザード形式にするために以下の形にテーブルを変更したい。
・Userテーブル(viewでは会員情報入力画面)

| Column             | Type    | Options     |
| ------------------ | ------- | ----------- |
| nickname           | string  | null: false |
| email              | string  | null: false |
| password           | string  | null: false |


・Identificationテーブル(viewでは本人確認入力画面)

| Column             | Type       | Options     |
| ------------------ | ---------- | ----------- |
| last_name          | string     | null: false |
| first_name         | string     | null: false |
| last_name_kana     | string     | null: false |
| first_name_kana    | string     | null: false |
| phone_number       | string     | null: false |
| user       　　　　 | references | optional: true |

## 1.テーブル・モデルの変更・追加
**1.Userテーブルの不要なカラム(last_nameやphone_numberなど)を以下のコマンドで削除していく。
完了したらマイグレート(rails db:migrate)を実行する。**

```:ターミナル
% rails g migration Removeカラム名From削除元テーブル名 削除するカラム名：型
↓ 
(例)
% rails g migration RemoveLastNameFromUsers last_name：string
```


**2.Identificationモデル・マイグレーションファイルを作成する**

```:ターミナル
% rails g model identification
```


**3.作成したIdentificationのマイグレーションファイルを編集し、マイグレート(rails db:migrate)を実行する。**

```ruby:2021***********_create_identifications
class CreateIdentifications < ActiveRecord::Migration[6.0]
  def change
    create_table :identifications do |t|
      t.string :last_name,          null: false
      t.string :first_name,         null: false
      t.string :last_name_kana,     null: false
      t.string :first_name_kana,    null: false
      t.string :phone_number,       null: false
      t.references :user
      t.timestamps
    end
  end
end
```

**4.Identificationモデルを編集する。**

```ruby:app/models/idetification.rb
class Identification < ApplicationRecord
  validates :phone_number, presence: true, length: { maximum: 11 }, format: { with: /\A[0-9]+\z/, message: 'ハイフンは必要ありません' }
  with_options presence: true, format: { with: /\A[ぁ-んァ-ン一-龥]+\z/, message: '全角文字を使用してください' } do
    validates :first_name
    validates :last_name
  end
  with_options presence: true, format: { with: /\A[ァ-ン]+\z/, message: '全角カナを使用してください' } do
    validates :first_name_kana
    validates :last_name_kana
  end

  belongs_to :user, optional: true 
end
```

**4.Userモデルを編集する。**
userテーブルとidentificationテーブルは1対1の関係なのでhas_oneを使用。

```ruby:app/models/user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  # 中略
  has_one :identification　#追記
end
```

## 2.ルーティングの変更
本人確認を登録するページを表示するnew_identificationと情報を保存するcreate_identificationを追記する。

```ruby:app/config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    registrations: "users/registrations",
  }
  #以下を追記する。
  devise_scope :user do
    get 'identification', to: 'users/registrations#new_identification'
    post 'identification', to: 'users/registrations#create_identification'
  end
  # 中略
end
```

## 3.Userコントローラーの変更
**1.ユーザー情報登録に関するコントローラー追記**

```ruby:app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  def new
    @user = User.new
  end

  def create
    @user = User.new(sign_up_params)
    render :new and return unless @user.valid?
    session['devise.regist_data'] = { user: @user.attributes }
    session['devise.regist_data'][:user]['password'] = params[:user][:password]
    @identification = @user.build_identification
    render :new_identification
  end
end
```
render :new and return unless @user.valid?
　→ユーザー登録情報の送られてきたパラメータがバリデーションに引っかかっていないかを確認している。

session['devise.regist_data'] = { user: @user.attributes }
session['devise.regist_data'][:user]['password'] = params[:user][:password]
　→ユーザー登録情報をsessionに保持させている。
　　1行目だけでは、パスワード情報が含まれていないため、2行目でパスワード情報を保持させる。

＠identification = @user.build_identification
render :new_identification
　→buildで次の本人確認で使用するインスタントを生成し、そのページで遷移させている。
<br>

**2.本人確認登録に関するコントローラー追記**

```ruby:app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  #中略
  def create_identification
    @user = User.new(session['devise.regist_data']['user'])
    @identification = Identification.new(identification_params)
    render :new_identification and return unless @identification.valid?
    @user.build_identification(@identification.attributes)
    @user.save
    session['devise.regist_data']['user'].clear
    sign_in(:user, @user)
    redirect_to root_path
  end

  private
  def identification_params
    params.require(:identification).permit(:last_name, :last_name_kana, :first_name, :first_name_kana, :phone_number)
  end
end
```
render :new_identification and return unless @identification.valid?
　→本人確認情報の送られてきたパラメータがバリデーションに引っかかっていないかを確認している。

@user.build_identification(@identification.attributes)
@user.save
　→本人確認情報と先ほどsessionに保持していたユーザー登録情報を保存している。

session['devise.regist_data']['user'].clear
　→保存が完了し、sessionに保持していたユーザー登録情報が不要になったので、削除している。

sign_in(:user, ＠user)
redirect_to root_path
　→ログインし、トップページに遷移している。

## 4.viewの変更
**1.views/devise/registrationsに本人確認を登録するためのviewファイル(new_identification.html.erb)を作成する。**
→**views / devise / registrations / new_identification.html.erb**

**2.作成したnew_identification.html.erbに本人確認用の入力フォームを記述していく。**

```html:views/devise/registrations/new_identification.html.erb
<%= form_with model: @identification, url: identification_path, method: :post, local: true do |f| %>
<div class='form-wrap'>
  <div class='form-header'>
    <h1 class='form-header-text'>
      本人確認
    </h1>
  </div>
  <div class="form-group">
    <div class='form-text-wrap'>
      <label class="form-text">お名前(全角)</label>
      <span class="indispensable">必須</span>
    </div>
    <!-- 中略　-->
  </div>
  <div class='hoge-btn'>
    <%= f.submit "会員登録" ,class:"hoge-btn" %>
  </div>
</div>
<% end %>
```

## 5.ウィザード形式に変更完了
これで、ユーザー情報登録画面と本人確認登録画面の2ページに分けることが出来た。
**ユーザー情報登録画面**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/941480/8a2e3e49-17d1-5a2d-ae36-14a98c9c6335.png" width=80%>

**本人確認登録画面**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/941480/e83d94b6-cb21-4b4c-d215-4daa43c8c847.png" width=80%>


## 最後に
今回の実装を通して、deviseのことも一緒に学ぶことが出来ました。
これまでdeviseはユーザー登録をするための便利なgemという認識しかなくsessionなどといった知識がほとんどなかったため、いい機会になりました。

##参考
以下の記事を参考にさせて頂きました。ありがとうございました。
sessionについて　https://qiita.com/nakanishi03/items/51ff2ade4cec078280d6
ウィザードについて　https://qiita.com/Tatsu88/items/7447a669b788b011e96b