LoginSignup
0
0

More than 3 years have passed since last update.

ユーザー管理機能をウィザード形式で実装する

Posted at

概要

今回は、ユーザー管理機能をウィザード形式で実装することに関してです。
ウィザード形式とは、画面遷移しながらユーザー登録を行っていく形式です。

今回、userモデルの登録要件は
nickname, grade, email, password

続いて画面遷移してuser_infoモデルに
subject, school, profile

を登録します。

ちなみに、user_infoは得意教科、在籍校、プロフィールとなっています。

実装

まずはdeviseをインストールして、userモデルを作成します。

emailとpasswordはデフォルトで入っているので、nicknameとgradeを追加します。

カラムを追加したので、次のようにコントローラーを編集します。

controllers.application_controller.rb
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname, :grade])
  end
end

次に、userモデルにバリデーションをかけます(コードは省略)

そして、ビューファイルを作ります。

views.devise.registrations.new.html.erb
<h2>ユーザー情報登録</h2>

<%= form_for(@user, url: user_registration_path) do |f| %>
  <%= render "devise/shared/error_messages", resource: @user %>

  <div class="field">
    <%= f.label :nickname %><br />
    <%= f.text_field :nickname %>
  </div>

  <div class="field">
    <%= f.label :grade %><br />
    <%= f.text_field :grade %>
  </div>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  <div class="field">
    <%= f.label :password %>
    <% if @minimum_password_length %>
    <em>(<%= @minimum_password_length %> characters minimum)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
  </div>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

ログイン画面を作ります。

views.home.index.html.erb
<h1>トップページ</h1>

<% if user_signed_in?%>
  <h2>ログインしています</h2>
  <%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
<% else %>
  <h2>ログインしていません</h2>
  <%= link_to "新規登録", new_user_registration_path %>
  <%= link_to "ログイン", new_user_session_path %>
<% end %>

画面遷移後のuser_infoモデルを作ります。

この時、外部キーとして、user_idを紐づけるのを忘れないようにします。

その後、userモデルとuser_infoモデルのアソシエーションを組みます。

次はdeviseのコントローラーを作成。

rails g devise:controllers users

次にルーティング。

routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }
  root to: "home#index"
end

ここまできたらuser_infoを登録する実装をしていきます。

registrationsコントローラーにnewメソッドを記述し、ビューファイルにformを入れます。

views/devise/registrations/new.html.erb
<%= form_for(@user, url: user_registration_path) do |f| %>
  <%= render "devise/shared/error_messages", resource: @user %>

---省略---

 <div class="actions">
    <%= f.submit "Next" %>
  </div>
<% end %>

ここからが少し記述が増えてきます。
createアクションを記述していきましょう。

controllers/users/registrations_controller.rb

def create
   @user = User.new(sign_up_params)
    unless @user.valid?
      render :new and return
    end
   session["devise.regist_data"] = {user: @user.attributes}
   session["devise.regist_data"][:user]["password"] = params[:user][:password]
   @user_info = @user.build_user_info
   render :new_user_info
 end

sessionを用いて1ページ目に記述したデータを持ってきます。
そしてattributesメソッドでデータを整形しています。

build_user_infoで今回生成したインスタンス@userに紐づくUserInfoモデルのインスタンスを生成します。ここで生成したUserInfoモデルのインスタンスは、@user_infoというインスタンス変数に代入します。そして、住所情報を登録させるページを表示するnew_user_infoアクションのビューへrenderします。

user_infoを登録させるページを表示するnew_user_infoアクションと住所情報を登録するcreate_user_infoアクションのルーティングを設定しましょう。

routes.rb
Rails.application.routes.draw do

  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }
  devise_scope :user do
    get 'user_infos', to: 'users/registrations#new_user_info'
    post 'user_infos', to: 'users/registrations#create_user_info'
  end

  resources :posts

  root to: "home#index"
end

このルーティングに書いた通り、user_infoを登録するビューファイルを作成していきます。

views/devise/registrations/new_user_info.html.erb
<h2>ユーザー情報登録</h2>

<%= form_for @user_info do |f| %>
  <%= render "devise/shared/error_messages", resource: @user_info %>

  <div class="field">
    <%= f.label :subject, "頑張りたい教科" %><br />
    <%= f.text_field :subject %>
  </div>

  <div class="field">
    <%= f.label :school, "学校名" %><br />
    <%= f.text_field :school %>
  </div>

  <div class="field">
    <%= f.label :profile, "自己紹介を記入しましょう" %><br />
    <%= f.text_area :profile %>
  </div>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

このuser_infoを保存する記述をコントローラーにしましょう。

controllers/users/registrations_controller.rb
def create_user_info
    @user = User.new(session["devise.regist_data"]["user"])
    @user_info = UserInfo.new(user_info_params)
      unless @user_info.valid?
        render :new_user_info
      end
    @user.build_user_info(@user_info.attributes)
    @user.save
    session["devise.regist_data"]["user"].clear
    sign_in(:user, @user)
  end

  protected

  def user_info_params
    params.require(:user_info).permit(:subject, :school, :profile)
  end

userをsaveした後に、.clearでsessionを削除しています。
そして、保存された後にログインされるように記述されています。

最後に、create_user_infoアクションに対応するビューを作成します。

views/devise/registrations/create_user_info.html.erb
<h2>登録が完了しました</h2>
<%= link_to "トップへ戻る", root_path%>

以上です。

感想

初めてウィザード形式の登録機能を実装しました。

本当はgradeの学年のところをactive_hashで実装したかったのですが、二時間エラーに悩まされた末に断念しました、、、

一通り実装してみて余裕があったらまたチャレンジしてみます。

日々頑張ってはいるのですが、あまり成長を感じられないです。
めちゃくちゃ記事みないと何もできません、、、

頑張ります。

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