#概要
今回は、ユーザー管理機能をウィザード形式で実装することに関してです。
ウィザード形式とは、画面遷移しながらユーザー登録を行っていく形式です。
今回、userモデルの登録要件は
nickname, grade, email, password
続いて画面遷移してuser_infoモデルに
subject, school, profile
を登録します。
ちなみに、user_infoは得意教科、在籍校、プロフィールとなっています。
#実装
まずはdeviseをインストールして、userモデルを作成します。
emailとpasswordはデフォルトで入っているので、nicknameとgradeを追加します。
カラムを追加したので、次のようにコントローラーを編集します。
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モデルにバリデーションをかけます(コードは省略)
そして、ビューファイルを作ります。
<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" %>
ログイン画面を作ります。
<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
次にルーティング。
Rails.application.routes.draw do
devise_for :users, controllers: {
registrations: 'users/registrations'
}
root to: "home#index"
end
ここまできたらuser_infoを登録する実装をしていきます。
registrationsコントローラーにnewメソッドを記述し、ビューファイルにformを入れます。
<%= 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アクションを記述していきましょう。
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アクションのルーティングを設定しましょう。
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を登録するビューファイルを作成していきます。
<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を保存する記述をコントローラーにしましょう。
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アクションに対応するビューを作成します。
<h2>登録が完了しました</h2>
<%= link_to "トップへ戻る", root_path%>
以上です。
#感想
初めてウィザード形式の登録機能を実装しました。
本当はgradeの学年のところをactive_hashで実装したかったのですが、二時間エラーに悩まされた末に断念しました、、、
一通り実装してみて余裕があったらまたチャレンジしてみます。
日々頑張ってはいるのですが、あまり成長を感じられないです。
めちゃくちゃ記事みないと何もできません、、、
頑張ります。