はじめに
チーム開発で、メルカリを模したアプリを開発しました。
その中で、”ウィザード形式”のユーザー登録機能を実装しました。
ウィザード形式とは
ユーザー登録ページが複数ページにわたり、全ての入力を終えてようやく登録される形式のことをいいます。
例
・1ページ目で名前・生年月日など基本情報を入力。ボタンを押して2ページ目へ。
・2ページ目で住所を入力。登録ボタンを押す。
・両ページに入力された情報が登録される。
といった具合です。
ウィザード形式においてポイントとなる"session"に関するコーディングを、
deviseのregistrations_controllerの
createアクション(登録1ページ目)と、
create_addressアクション(登録2ページ目)に
記述しました。
※今回、usersテーブルとship_addressesテーブルを設定しました。
最終的に、登録1ページ目のデータが前者に、2ページ目のデータが後者に保存されます。
実装後にやってみたこと
そのコーディングで具体的に何をしているのか?自分なりにまとめてみました。
■自分の中のあるある(言いたい)
User.new(session["devise.regist_data"]["user"])の( )内のような独特な記載のコードを目にすると、”なんとなくこんなことしてるんだろな〜”ぐらいに軽く流し読みしがち。
↓
今回チームメンバーにコーディング解説(!)する場面がありましたので、良い機会だと思い、メンターに質問するなどしてコーディング詳細を調べてみました。
■そもそもsessionとは
こちらの記事がわかりやすくてお世話になりました!😀
https://qiita.com/ozackiee/items/4ee774c81b2a0c571c05
■sessionを使う1つのメリット
1ページ目の登録を終え、2ページ目に進むも、途中で入力中断、のような状況の時に、
中途半端な情報を登録せずに済みます。
sessionをうまく使って、1ページ目・2ページ目ともに入力して初めて登録完了するように
コーディングしています。
■環境
rails (5.2.4.2)
devise (>= 4.7.1)
registrations_controllerに書いたコードと解説(解説もセットでご覧ください)
def create
@user = User.new(sign_up_params) #登録1ページ目から送られてきたパラメータを@userに代入
unless @user.valid? #validメソッドを使ってバリデーションチェック
flash.now[:alert] = @user.errors.full_messages #入力漏れがあればエラーメッセージを表示
render :new and return #and returnを使って条件分岐を明示的に終了させている。
end
session["devise.regist_data"] = {user: @user.attributes}
#sessionにハッシュオブジェクトで情報保持させるため、attributesメソッドでデータ整形。
#user: というようにシンボル型で記述している。
session["devise.regist_data"][:user][:password] = params[:user][:password]
#前述ではパスワードを代入出来ていないので、この行で代入。
#params[:user][:password]において、paramsの中身(userモデルのpasswordカラム)から値を取り出している。ネスト構造な書き方。
# (params[:password]ではなく、params[:user][:password]という書き方で、モデル・カラムという順番で指定している)
#その値をsession["devise.regist_data”]の中の[:user]というハッシュの[:password]というキーのバリューに代入している。
#今回ひとつ前のコードでシンボル型を用いているので、ここのコードも型を合わせている。
#もしもひとつ前のコードで文字列型("user")を用いている場合は、ここのコードも文字列型にする必要がある。
@address = @user.build_ship_address
#build_ship_addressメソッドはhas_one :ship_addressのアソシエーションを設定していると使用可。関連づけのあるnewメソッドのようなもの。
render :new_address #登録2ページ目に遷移
end
def create_address
@user = User.new(session["devise.regist_data"]["user"])
#session["devise.regist_data”]の中の["user”]というハッシュの情報を@userに代入している。
#userという同じハッシュがアクションをまたぐ(create~create_address)と、create_addressアクションにおいては自動的に文字列になってしまう。
#そのためcreate_addressアクションでは文字列表記で指定しないといけない。
#binding.pryで実際に検証すると、文字列表記でパラメータが飛んでいることが確認できる。
@address = ShipAddress.new(address_params)
unless @address.valid?
flash.now[:alert] = @address.errors.full_messages
render :new_address and return
end
@user.build_ship_address(@address.attributes) #送られてきたparamsをbuild_ship_addressを用いて@userに代入
@user.save
session["devise.regist_data"]["user"].clear #sessionを明示的に削除 セキュリティ上必要
sign_in(:user, @user) #登録後ログイン状態になるようにしている
redirect_to complete_users_path
end
という感じで
1つ1つの記載がどんなオブジェクト・メソッドなのか紐解いてみました。
いざ自分でエディタにコメントで意味を書き出してみると、かなり良いアウトプットになるなと感じました。
1行1行細かく見ていくのでそれなりに時間はかかりましたが、とても勉強になったので、やって良かったです。
(チームメンバーのみんなに感謝!!)
何かありましたらご指摘等いただければ幸いです。
以上、ご覧いただきありがとうございました!