はじめに
オリジナルアプリ制作にあたり、ユーザー登録時にウィザード形式(対話するように順番に操作が進んでいく方式)を用いるように変更しました。
ウィザード形式にすることで、ユーザーからすると見やすく使いやすいとのことだったため、変更することにしました。
変更前はユーザー登録と本人確認が以下の画像のように一緒の画面にある状態。
1ページが縦長になってしまい、少しわかりづらい。(スクショにも全部納まっていないし…。)
なので、今回はユーザー情報登録画面と本人確認登録画面に2ページに分けていきたいと思います。
変更前・変更後のテーブルの状態
変更前
現状、会員情報入力と本人確認が同じテーブルになっている。
・Userテーブル
Column | Type | Options |
---|---|---|
nickname | string | null: false |
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 |
変更後
ウィザード形式にするために以下の形にテーブルを変更したい。
・Userテーブル(viewでは会員情報入力画面)
Column | Type | Options |
---|---|---|
nickname | string | null: false |
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)を実行する。
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モデルを編集する。
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を使用。
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
# 中略
has_one :identification #追記
end
2.ルーティングの変更
本人確認を登録するページを表示するnew_identificationと情報を保存するcreate_identificationを追記する。
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.ユーザー情報登録に関するコントローラー追記
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で次の本人確認で使用するインスタントを生成し、そのページで遷移させている。
2.本人確認登録に関するコントローラー追記
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に本人確認用の入力フォームを記述していく。
<%= 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ページに分けることが出来た。
ユーザー情報登録画面
最後に
今回の実装を通して、deviseのことも一緒に学ぶことが出来ました。
これまでdeviseはユーザー登録をするための便利なgemという認識しかなくsessionなどといった知識がほとんどなかったため、いい機会になりました。
##参考
以下の記事を参考にさせて頂きました。ありがとうございました。
sessionについて https://qiita.com/nakanishi03/items/51ff2ade4cec078280d6
ウィザードについて https://qiita.com/Tatsu88/items/7447a669b788b011e96b