Help us understand the problem. What is going on with this article?

Rails Deviseでユーザー編集をパスワードを入力しないで更新する方法

Rails Deviseでユーザー編集をパスワードを入力しないで更新する方法

Deviseで現在のパスワードを入力せずにユーザ情報を更新する方法をまとめます。

目次

動作環境

OS : macOS Mojave 10.14.6
ruby : 2.6.5p114
rails : 5.2.4
devise : 4.7.1

前提条件

すでにgemのインストールからviewの作成までの手順が終わっていると仮定します。

  1. devise gemのインストール済
  2. rails generate devise install済
  3. rails generate devise:views済
  4. usersテーブルにnameなどのデフォルト以外のカラムが追加済

手順概略

STEP1. 新規登録のためのストロングパラメータをapplication_controllerに追加

STEP2. registrations_controller.rbcontrollers/users/に作成し,更新するためのストロングパラメータを追加, ルーティングを修正

STEP3. パスワード無しでアップデートするためのメソッドをregistrations_controller.rbuser.rbに記載

STEP4. Viewからcurrent_passwordフィールドを削除する

詳細手順

新規登録のためのストロングパラメータの設定

現状では後から追加したnameのパラメータはstrongパラメータではじかれてしまうため
application_controllerに以下のコードを記載します.

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: [: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の入力フィールドを記載します.

new.html.erb
<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フィールドを追加します.

edit.html.erb
//追加
<div class="field">
  <%= f.label :name %><br />
  <%= f.text_field :name, autofocus: true, autocomplete: "name" %>
</div>

ここでアップデートボタンを押してもnameはupdateされないことがわかります.

そこでnameカラムをアップデートするためにusers/registrations_controller.rbを作成し,以下のように記載します.

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を参照するためにルーティングを修正します.

routes.rb
Rails.application.routes.draw do
  root 'blogs#index'
  #変更箇所
  devise_for :users, controllers: {
    registrations: 'users/registrations'
  }
  resources :blogs
  end

するとUsersのnameカラムがアップデートできるようになります.

パスワード無しで更新するためのメソッドを定義

ただ,現時点ではcurrent_passwordを入力しないとupdateの際にエラーになります.
image.png

そこで, まずはuserモデルにパスワード無しでアップデートするメソッドを定義します.

user.rb
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を呼び出します.

registrations_controller.rb
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を削除します.

edit.html.erb
//削除
<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>

結果

image.png

エラーが出ずにuser nameがアップデートされていることがわかります.

image.png

j-sunaga
日常の業務・学習で気づいたことをまとめています.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away