0
0

More than 3 years have passed since last update.

Rails ウィザード形式のユーザー登録機能実装 コントローラの記述(session, ハッシュ等)を紐解いてみた

Last updated at Posted at 2020-05-08

はじめに

チーム開発で、メルカリを模したアプリを開発しました。
その中で、”ウィザード形式”のユーザー登録機能を実装しました。

ウィザード形式とは
ユーザー登録ページが複数ページにわたり、全ての入力を終えてようやく登録される形式のことをいいます。


・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に書いたコードと解説(解説もセットでご覧ください)

registrations_controller.rb
  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行細かく見ていくのでそれなりに時間はかかりましたが、とても勉強になったので、やって良かったです。
(チームメンバーのみんなに感謝!!)

何かありましたらご指摘等いただければ幸いです。
以上、ご覧いただきありがとうございました!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0