#Rails Deviseでユーザー編集をパスワードを入力しないで更新する方法
Deviseで現在のパスワードを入力せずにユーザ情報を更新する方法をまとめます。
目次
動作環境
OS : macOS Mojave 10.14.6
ruby : 2.6.5p114
rails : 5.2.4
devise : 4.7.1
前提条件
すでにgemのインストールからviewの作成までの手順が終わっていると仮定します。
- devise gemのインストール済
- rails generate devise install済
- rails generate devise:views済
- usersテーブルにnameなどのデフォルト以外のカラムが追加済
手順概略
[STEP1. 新規登録のためのストロングパラメータをapplication_controller
に追加]
(#新規登録のためのストロングパラメータの設定)
STEP2. registrations_controller.rb
をcontrollers/users/
に作成し,更新するためのストロングパラメータを追加, ルーティングを修正
STEP3. パスワード無しでアップデートするためのメソッドをregistrations_controller.rb
とuser.rb
に記載
STEP4. Viewからcurrent_passwordフィールドを削除する
詳細手順
新規登録のためのストロングパラメータの設定
現状では後から追加したnameのパラメータはstrongパラメータではじかれてしまうため
application_controllerに以下のコードを記載します.
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
end
end
コンソールで確認するとnameパラメータを受け取りユーザを作成できています.
irb(main):001:0> User.create(name: 'abc' , email:'abc@example.com',password:'123456')
(1.3ms) COMMIT
=> #<User id: 2, email: "abc@example.com", created_at: "2020-05-30 10:41:46", updated_at: "2020-05-30 10:41:46", name: "abc">
次はviewにnameの入力フィールドを記載します.
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
//追加
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name, autofocus: true, autocomplete: "name" %>
</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" %>
これでuserの新規登録は完了です。
アップデートのストロングパラメータの設定
次にユーザ編集用のviewにもnameフィールドを追加します.
//追加
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name, autofocus: true, autocomplete: "name" %>
</div>
ここでアップデートボタンを押してもnameはupdateされないことがわかります.
そこでnameカラムをアップデートするためにusers/registrations_controller.rb
を作成し,以下のように記載します.
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_account_update_params, only: [:update]
protected
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:name])
end
end
そして、このregistartions_controller
を参照するためにルーティングを修正します.
Rails.application.routes.draw do
root 'blogs#index'
#変更箇所
devise_for :users, controllers: {
registrations: 'users/registrations'
}
resources :blogs
end
するとUsersのnameカラムがアップデートできるようになります.
パスワード無しで更新するためのメソッドを定義
ただ,現時点ではcurrent_passwordを入力しないとupdateの際にエラーになります.
そこで, まずはuserモデルにパスワード無しでアップデートするメソッドを定義します.
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
//追加するメソッド
def update_without_current_password(params, *options)
params.delete(:current_password)
if params[:password].blank? && params[:password_confirmation].blank?
params.delete(:password)
params.delete(:password_confirmation)
end
result = update_attributes(params, *options)
clean_up_passwords
result
end
end
その後,registrations_controller
からupdate_without_password
を呼び出します.
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_account_update_params, only: [:update]
protected
//追加(必須)
def update_resource(resource, params)
resource.update_without_password(params)
end
//必須ではないがupdate後にtop画面にリダイレクトするメソッド
def after_update_path_for(_resource)
blogs_path
end
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:name])
end
end
viewファイルからcurrent_passwordフィールドの削除
viewファイルからcurrent_password
を削除します.
//削除
<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>
結果
エラーが出ずにuser nameがアップデートされていることがわかります.