エンジニア転職日記

エンジニア転職に向けての日記です

How to devise (カスタマイズ)

概要

deviseにによるユーザー管理機能の続きです。

 

shangang7321.hatenablog.com

 

 

実装条件

以下のようなテーブルにデータを保存できるように実装していきます。

新規登録・ログイン・ログアウトを作成します。

メルカリのようなイメージです。

## users テーブル
| Column | Type | Options |
| -------- | ------ | ----------- |
| nickname | string | null: false |
| email | string | null: false |
| password | string | null: false |
| family_name | string | null: false |
| first_name | string | null: false |
| family_name_kana | string | null: false |
| first_name_kana | string | null: false |
| birthday | integer | null: false |

 

実装工程

ビューファイルの設置

まずは、ビューファイルを設置していきます。

viewファイルの生成は、以下のコマンドです。

% rails g devise:views

 

今回は課題として配布されたデータを使いました。

ビューファイルの設置が終わったら、フォームヘルパーの設定を行なっていきます。

# views/devise/registrations/new.html.erb
<%= form_with class: 'registration-main', model: resource, as: resource_name,
url: registration_path(resource_name), local: true do |f| %>
# 中略
<%= f.text_area :nickname, class:"input-default", placeholder:"例) furima太郎",
maxlength:"40" %>
 # 中略
<%= f.email_field :email, class:"input-default",
placeholder:"PC・携帯どちらでも可", autofocus: true %>
 # 中略
<%= f.password_field :password, class:"input-default",
placeholder:"6文字以上の半角英数字" %>
# 中略
<%= f.password_field :password_confirmation, class:"input-default",
placeholder:"同じパスワードを入力して下さい" %>
 # 中略
<%= f.text_area :family_name, class:"input-name", placeholder:"例) 山田" %>
<%= f.text_area :first_name, class:"input-name", placeholder:"例) 陸太郎" %>
 # 中略
<%= f.text_area :family_name_kana, class:"input-name",
placeholder:"例) ヤマダ" %>
<%= f.text_area :first_name_kana, class:"input-name",
placeholder:"例) リクタロウ" %>
# 中略
<%= raw sprintf(
f.date_select(
:birthday,
class:'select-birth',
use_month_numbers: true,
prompt:'--',
start_year: 1930,
end_year: (Time.now.year - 5),
date_separator: '%s'),
"<p> 年 </p>", "<p> 月 </p>") + "<p> 日 </p>" %>
 

 

# views/devise/sessions/new.html.erb 
<%= form_with model: resource,class: 'registration-main', as: resource_name,
url: session_path(resource_name), local: true do |f|%>
 # 中略
<%= f.email_field :email, class:"input-default",
placeholder:"PC・携帯どちらでも可", autofocus: true %>
 # 中略
<%= f.password_field :password, class:"input-default", placeholder:"" %>

 

バリデーションのエラーメッセージをif文で分岐させて表示させます。

# views/shared/_error_messages.html.erb
<% if model.errors.any? %>
<div class="error-alert">
<ul>
<% model.errors.full_messages.each do |message| %>
<li class='error-message'><%= message %></li>
<% end %>
</ul>
</div>
<% end %>

 

ログインしている時はnicknameとログアウトボタンを、

ログインしていない時はログインボタンとログアウトボタンを表示させます。

# views/shared/_header.html.erb
<% if user_signed_in? %>
<li><%= link_to current_user.nickname, "#", class: "user-nickname" %></li>
<li><%= link_to 'ログアウト', destroy_user_session_path ,
method: :delete, class: "logout" %></li>
<% else %>
<li><%= link_to 'ログイン', new_user_session_path, class: "login" %></li>
<li><%= link_to '新規登録',new_user_registration_path ,
class: "sign-up" %></li>
<% end %>

 

ポイントは以下です。

 

<%= form_with model: resource,class: 'registration-main', as: resource_name,
url: session_path(resource_name), local: true do |f|%>

deviseを利用する時、model: resource, as: resource_nameと設定します。

deviseの中での処理が行われる際にこの引数でないとcurrent_userなどのメソッドがうまく機能しないことがあります。

 

<%= raw sprintf(
f.date_select(
:birthday,
class:'select-birth',
use_month_numbers: true,
prompt:'--',
start_year: 1930,
end_year: (Time.now.year - 5),
date_separator: '%s'),
"<p> 年 </p>", "<p> 月 </p>") + "<p> 日 </p>" %>
この記述によって、誕生日が年、月、日と別れてセレクトボックスになっています。
 
<% if user_signed_in? %>
user_signed_in?メソッドは、deviseのメソッドです。サインインしている状態ならばtrueが返ってきます。
 
<li><%= link_to current_user.nickname, "#", class: "user-nickname" %></li>
current_userメソッドもdeviseのメソッドです。サインインしている状態であれば、そのユーザーのレコードを引き出せます。
 

コントローラーの設定

コントローラーの生成を行います。

rails g devise:controllers users

 

ルーティングの設定をします。今回は新規登録とログイン機能のみなので、以下のようになります。

devise_for :users, controllers: {
registrations: 'users/registrations',
sessions: 'users/sessions'
}

 

コントローラーの設定に移ります。

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, :family_name,
:first_name, :family_name_kana, :first_name_kana, :birthday])
end
end

devise_parameter_sanitizerメソッドは、deviseのストロングパラメーターです。各キーを許可しています。

 

require 'date'
class Users::RegistrationsController < Devise::RegistrationsController
def create
params[:user][:birthday] = birthday_join
@user = User.new(user_params)
if @user.save
sign_up(resource_name, resource)
redirect_to root_path
else
render :new
end
end
private
def user_params
params.require(:user).permit(:nickname, :email, :password,
:password_confirmation, :family_name, :first_name,
:family_name_kana, :first_name_kana, :birthday)
end
def birthday_join
return if params[:user]['birthday(1i)'].empty?
&& params[:user]['birthday(2i)'].empty?
&& params[:user]['birthday(3i)'].empty?
Date.new(params[:user]['birthday(1i)'].to_i,
params[:user]['birthday(2i)'].to_i,
params[:user]['birthday(3i)'].to_i)
end 
end

 

createアクションを設定しています。birthday_joinメソッドは、フォームヘルパーから送られてくる誕生日のデータをまとめてDateクラスのインスタンスにする作業を行なっています。

空欄があると保存の時にエラーが出てしまうので、empty?メソッドで空でないか確かめています。

そのあと、インスタンスを生成し、deviseのsign_upメソッドを使って新規登録を完了させています。

 

class Users::SessionsController < Devise::SessionsController
def create
super
end
end

 

ログインはシンプルに、deviseのデフォルトのcreateアクションを利用します。

以上でビュー、コントローラーの設定は完了です。

 

参考

https://note.com/vixer93/n/nac92cc4c0983

https://github.com/heartcombo/devise