Rails ウィザード形式導入について 2

#はじめに
[Rails ウィザード形式導入について 1 はこちらをクリック願います。](https://qiita.com/raigakun/items/71cd599a0d66bf46f581)
チーム開発でフリマサイトを開発致しました。
その際、ユーザーの新規登録画面でウィザード形式を導入致しましたので、内容を整理します。
もうすでにご存知の方、省略の仕方等ご存知でしたら、ご教授願います。

#前提
- ユーザー情報(User)については　以下　**A**　と記述します。
- 住所情報(Destination)については　以下　**B**　と記述します。


#Aの新規登録のnewアクションとビュー
- app/controllers/users/registrations_controller.rbを見てみてください。
- えらいことになっているかと思います・・・
- なんだこれ・・・

```app/controllers/users/registrations_controller.rb
# frozen_string_literal: true

class Users::RegistrationsController < Devise::RegistrationsController
  # before_action :configure_sign_up_params, only: [:create]
  # before_action :configure_account_update_params, only: [:update]

  # GET /resource/sign_up
  # def new
  #   super
  # end

  # POST /resource
  # def create
  #   super
  # end

  # GET /resource/edit
  # def edit
  #   super
  # end

  # PUT /resource
  # def update
  #   super
  # end

  # DELETE /resource
  # def destroy
  #   super
  # end

  # GET /resource/cancel
  # Forces the session data which is usually expired after sign
  # in to be expired now. This is useful if the user wants to
  # cancel oauth signing in/up in the middle of the process,
  # removing all OAuth session data.
  # def cancel
  #   super
  # end

  # protected

  # If you have extra params to permit, append them to the sanitizer.
  # def configure_sign_up_params
  #   devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute])
  # end

  # If you have extra params to permit, append them to the sanitizer.
  # def configure_account_update_params
  #   devise_parameter_sanitizer.permit(:account_update, keys: [:attribute])
  # end

  # The path used after sign up.
  # def after_sign_up_path_for(resource)
  #   super(resource)
  # end

  # The path used after sign up for inactive accounts.
  # def after_inactive_sign_up_path_for(resource)
  #   super(resource)
  # end
end
```

- コメントアウトしている箇所はすでにDevise::RegistrationsControllerで定義されているものです。
- コメントアウト部分を外して上書きすることができます。（メソッドのオーバーライド）
- superはスーパークラス（今回であればDevise）のメソッドを呼び出しています。


#### とりあえずコメントアウト部分(superクラスの呼び出し部分）を全部消してしまいます・・・
- deviseとUserモデルが紐づくように設定してあるので、superで呼び出してもdeviseは同様の操作を行ってくれるようです。
- 勉強中ですので、super呼び出し方法についてはお待ちください（泣）

#### newアクションを定義する
```app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController

  def new
    @user = User.new
  end

end

```

#### そして、対応しているビューも編集する
- 参考程度にみてください。このまま入力するとエラーが出るかも・・・です。

```app/views/devise/registrations/new.html.haml
  .main
    .title
      .title__font
        A情報入力

    = form_for(@user, url: user_registration_path) do |f|
      .name-information
        .name-information__item
          .name-information__item__nicname
            = f.label :name,"ニックネーム"
        .name-information__name
          = f.text_field :name,size:26
      .email
        .email__information
          .email__information__address
            = f.label :email,"メールアドレス"
        .email__information
          = f.email_field :email, autofocus: true, autocomplete: "email",size:26

      .password
        .password__item
          .password__item__pass
            = f.label :password,"パスワード"
          .password__item__note
            - if @minimum_password_length
              (#{@minimum_password_length} 文字以上必要です)
        .password__input
        .password__description
          = f.password_field :password, autocomplete: "new-password", size:26

      .re-enter
        .re-enter__item
          .re-enter__item__pass
            = f.label :password_confirmation,"確認用パスワード "
        .re-enter__itempass
          = f.password_field :password_confirmation, autocomplete: "new-password",size:26
      .terms-of-service
        .terms-of-service__btm
          %input#submit_button1{:name => "submit", :type => "submit", :value => "次へ進む"}/
     
      
```



#Aの新規登録のcreateアクションとビュー
- 1ページ目で入力した情報のバリデーションチェックをします。
- 1ページで入力した情報をsessionに保持させます。
- 次の**B**の登録で使用するインスタンスを生成、当該ページへ遷移するようにします。


#### createアクションを定義する(追記してください)
```app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create]

# 省略

  def create
    @user = User.new(sign_up_params)
    unless @user.valid?
      flash.now[:alert] = @user.errors.full_messages
      render :new and return
    end
    session["devise.regist_data"] = {user: @user.attributes}
    session["devise.regist_data"][:user]["password"] = params[:user][:password]
    @destination = @user.build_destination
    render :new_destination
  end



  protected

  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute])
  end

end
```
#####1ページ目で入力した情報のバリデーションチェック

- Userモデルのインスタンスを生成する。
- 1ページ目から送られてきたパラメータをインスタンス変数@userに代入する。
- そのインスタンス変数に対してvalid?メソッドを適用する。
- 送られてきたパラメータが指定されたバリデーションに違反しないかどうかチェックすることができる。
- falseになった場合は、エラーメッセージとともにnewアクションへrenderする。

#####1ページで入力した情報をsessionに保持させる

- **A**情報だけではなく、**B**情報までページ遷移した後に保存するという機能を達成するのが目的です。
- そのために、sessionという機能を用いる。
- sessionとは、ページが遷移しても情報が消えることが無いように、クライアント側で保持をさせておく機能のことをいうようです。
- **A**情報のバリデーションチェック後、session["devise.regist_data"]に値を代入する。
- この時、sessionにハッシュオブジェクトの形で情報を保持させるために、attributesメソッドを用いてデータを生成する。
- また、paramsの中にはパスワードの情報は含まれているが、attributesメソッドでデータ整形をした際にパスワードの情報は含まれない。
- そこで、パスワードを再度sessionに代入する。

#####B情報登録で使用するインスタンスを生成、B情報登録ページへ遷移する

- 次ページで、ユーザーモデルに紐づくB情報を入力させるため、該当するインスタンスを生成しておく必要がある。
- そのために、build_destinationで今回生成したインスタンス@userに紐づくDestinationモデルのインスタンスを生成する。
- ここで生成したDestinationモデルのインスタンスは、@destinationというインスタンス変数に代入する。
- そして、B情報を登録させるページを表示するnew_destinationアクションのビューへrenderする。



###難しい！でも自作アプリには入れたいです！もうひと頑張り！

続きは次回！

#さいごに
日々勉強中ですので、随時更新します。
皆様の復習にご活用頂けますと幸いです。