はじめに
RubyOnRailsでdeviseを用いたユーザー管理登録機能のユーザー情報の編集機能の実装についてまとめていきたいと思います。
目的
- deviseのユーザー管理機能のユーザー情報編集を実装する
- ユーザー情報を編集する際に、新規登録で登録したパスワードを入力なしで変更できるようにする
- ユーザー情報を登録した後の遷移先を変更する
この記事の前提としてdeviseやdeviseのビューのインストールはすでに導入し、新規登録の実装が終わっているものとします。
環境
devise (4.9.2)
ruby 3.2.0
Rails 7.0.8
実装の流れ
- deviseのコントローラーをインストール
- ルーティングを設定
- ストロングパラメーターを追加(デフォルトのカラム以外を設定している場合のみ)
- ビューの編集(マイページに遷移するボタンを設定→ユーザー情報編集ページ)
- コントローラーをカスタマイズ
- 編集が終了した後の遷移先の変更
1.deviseのコントローラーをインストール
$ rails g devise:controllers users
上記コマンドを実行すると、app/controllers/users
以下に6つのDevise用のコントローラーが自動生成されます。
ちなみに生成されたものがどのようなものなのかは、こちらのブログの記事を参考にしてください。
2.ルーティングを設定
Rails.application.routes.draw do
devise_for :users, controllers: {
registrations: "users/registrations",
sessions: "users/sessions",
passwords: "users/passwords",
confirmations: "users/confirmations"
}
# 「, controllers:{~省略~}」を追記する
root to: 'messages#index'
resources :messages, only: :index
resources :users, only: [:show]
end
devise_for :users,
の後ろにcontrollers:{~省略~}
を追記します。
追記することで、1で生成したコントローラーへのルーティングを設定することができます。
3.deviseコントローラーにストロングパラメーターを追加(デフォルトのカラム以外を設定している場合のみ)
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
private
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :profile])
devise_parameter_sanitizer.permit(:account_update, keys: [:name, :profile])
# 上記の記述を追加
end
end
deviseで設定されているカラム以外に追加されている方は、ユーザー情報編集時のストロングパラメーターを追加する必要があります。
devise_parameter_sanitizer.permit(:account_update, keys: [:name, :profile])
今回の場合、:name, :profile
を追加する必要があったので上記のように記述しました。
状況に応じて、カラム名を編集する必要があります。
4.ビューの編集(マイページに遷移するボタンを設定→ユーザー情報編集ページ)
<%= link_to "ユーザー情報編集", edit_user_registration_path(current_user.id), class: "header-button" %>
マイページにユーザー情報編集ページへのボタンを設定しました。
<h2>Edit <%= resource_name.to_s.humanize %></h2>
# ---------- 下の記述を削除 ----------
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
# ---------- 上の記述を削除 ----------
# ---------- (1)下の記述を追加 ----------
<%= form_with model: @user, url: registration_path(resource_name), local: true do |f| %>
<%= render "devise/shared/error_messages", model: f.object %>
# ---------- (1)上の記述を追加 ----------
# ---------- (2)下の記述を追加 ----------
<div class="field">
<%= f.label :name, "name" %><br />
<%= f.text_field :name, autofocus: true %>
</div>
# ---------- (2)上の記述を追加 ----------
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>
# ---------- (2)下の記述を追加 ----------
<div class="field">
<%= f.label :profile, "profile" %>
<%= f.text_field :profile %>
</div>
# ---------- (2)上の記述を追加 ----------
<div class="field">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, autocomplete: "new-password" %>
<% if @minimum_password_length %>
<br />
<em><%= @minimum_password_length %> characters minimum</em>
<% end %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
# ---------- (3)下の記述を削除 ----------
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password, autocomplete: "current-password" %>
</div>
# ---------- (3)上の記述を削除 ----------
<div class="actions">
<%= f.submit "Update" %>
</div>
<% end %>
<h3>Cancel my account</h3>
<div>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %></div>
<%= link_to "Back", :back %>
デフォルトのedit.html.erb
を編集をしました。編集内容は以下のとおりです。
-
form_for
からform_with
の記述に変更(shared/error_messages
の記述も変更しないとエラーが出ます) -
:name, :profile
の記入欄を追加 - ユーザー情報を編集する際に元の設定されたパスワードを入力する欄を削除(次の項目で説明します)
5.コントローラーをカスタマイズ
# 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
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 省略 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# The path used after sign up for inactive accounts.
# def after_inactive_sign_up_path_for(resource)
# super(resource)
# end
# ---------- 下の記述を追加 ----------
protected
def update_resource(resource, params)
resource.update_without_current_password(params)
end
# ---------- 上の記述を追加 ----------
end
パスワードなしで、パスワードの更新を可能にするには自分でメソッドを定義する必要があります。
update_without_current_password
をuser.rb
に定義していきます。
詳しくは以下の記事を参考にしてください。
https://easyramble.com/user-account-update-without-password-on-devise.html
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
with_options presence: true do
validates :radio_name, length: { maximum: 7 }
end
validates :profile, length: { maximum: 140 }
VALID_PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]+\z/i
validates :password, format: { with: VALID_PASSWORD_REGEX }
# ---------- 下の記述を追加 ----------
def update_without_current_password(params, *options)
if params[:password].blank? && params[:password_confirmation].blank?
params.delete(:password)
params.delete(:password_confirmation)
end
result = update(params, *options)
clean_up_passwords
result
end
# ---------- 上の記述を追加 ----------
end
上記の記述をすることで、パスワードの更新を実装することができました。
6.編集が終了した後の遷移先の変更
deviseのデフォルトの設定では、ユーザー情報を編集したらトップページにリダイレクトされるように設定されています。
その設定を変更するためにコントローラーに記述します。
# 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
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 省略 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# The path used after sign up for inactive accounts.
# def after_inactive_sign_up_path_for(resource)
# super(resource)
# end
protected
def update_resource(resource, params)
resource.update_without_current_password(params)
end
# ---------- 下の記述を追加 ----------
def after_update_path_for(resource)
user_path(current_user.id)
end
# ---------- 上の記述を追加 ----------
end
編集後、ユーザーのマイページに遷移するように設定しました。
最後に
deviseのユーザー情報編集機能は今回初めて実装しました。
編集機能についてのブログの記事を頼りに、なんとか実装することができました。
この記事のコードや仕組みの解釈に関して、誤りや改善点などありましたら、是非ご指摘いただけると幸いです。