前提・実現したいこと
ご覧いただきありがとうございます。
deviseで用意されたviewをカスタマイズしてユーザーがpasswordを変更できるようにしたく、質問させて頂きます。
発生している問題・ソースコード
認証機能にdeviseを使って自作アプリを作成しています。
user/edit(ユーザー情報の変更)画面でupdateする際に、current_password
を入力しなくても更新できるようにしたいと考え、この記事を参考に、
class RegistrationsController < Devise::RegistrationsController
protected
def update_resource(resource, params)
resource.update_without_password(params)
end
end
を追記し、routes.rbも編集して無事にcurrent_password
なしで更新できるようになりました。
しかしこうすると、editページからpasswordが編集できないようになってしまうということをこのサイトで知ったので、このサイト通りに実装してみました。
しかし、他の要素(nameやemail)は問題なく更新されるにも関わらず、passwordだけは更新されずに困っています。
以下、私のソースコードです。
registrations_controller.rb
# 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
# POST /resource
# def create
# super
# end
# GET /resource/edit
# def edit
# super
# end
# PUT /resource
# def update
# super
# end
# DELETE /resource
# def destroy
# super
# end
# GET /resource/cancel
# Forces the session data which is usually expired after sign
# in to be expired now. This is useful if the user wants to
# cancel oauth signing in/up in the middle of the process,
# removing all OAuth session data.
# def cancel
# super
# end
protected
# If you have extra params to permit, append them to the sanitizer.
# def configure_sign_up_params
# devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute])
# end
# If you have extra params to permit, append them to the sanitizer.
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:name])
devise_parameter_sanitizer.permit(:account_update, keys: [:attribute])
end
def update_resource(resource, params)
resource.update_without_current_password(params)
end
# The path used after sign up.
def after_sign_up_path_for(resource)
user_path(current_user)
end
# The path used after sign up for inactive accounts.
# def after_inactive_sign_up_path_for(resource)
# # my_page_path(resource)
# # end
end
app/models/user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
# deviseで使うモジュールたち。
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
# 自分で追加したカラムにバリデーションをかけておく
validates :name, presence: true, length: {maximum: 50}
#ここから
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
routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => {
:registrations => 'users/registrations',
:sessions => 'users/sessions',
:passwords => 'users/passwords'
}
devise_scope :user do
get "/users/sign_out" => "devise/sessions#destroy"
end
resources :users
end
app/views/devise/registrations/edit.html.erb(パスワードの部分とsubmitボタンの部分の抜粋)
<div class="form-group">
<%= f.password_field :password, autocomplete: "new-password" ,:placeholder => "password",
id: "password", class: "form-control"%>
<small class="form-text password_help_text">(6文字以上) パスワードの変更が不要な場合は空欄のままUpdateボタンを押してください</small>
</div>
<div class="form-group">
<%= f.password_field :password_confirmation, autocomplete: "new-password", id: "password_confirmation",
:placeholder => "パスワードを再入力してください", class: "form-control"%>
</div>
<div class="text-right">
<%= f.submit "Update", class: "submit-button" %>
</div>
該当すると思われるコードは記載させて頂きましたが、もし何か不足があれば教えて頂けますと幸いです。
丸一日使ってしまいましたがどうしても解決せず...
何か少しでも心当たりのある方がいらっしゃいましたら、どうかお力をお貸し頂けないでしょうか。
どうぞよろしくお願いします。
[追記]
update実行時のサーバーログです。
Started GET "/users/edit" for ::1 at 2019-09-01 07:51:37 +0900
Processing by Users::RegistrationsController#edit as HTML
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 3], ["LIMIT", 1]]
Rendering devise/registrations/edit.html.erb within layouts/application
Rendered devise/shared/_error_messages.html.erb (Duration: 0.2ms | Allocations: 15)
Rendered devise/registrations/edit.html.erb within layouts/application (Duration: 3.8ms | Allocations: 591)
Rendered layouts/_header.html.erb (Duration: 3.3ms | Allocations: 1255)
Rendered layouts/_flash.html.erb (Duration: 0.1ms | Allocations: 17)
Rendered layouts/_footer.html.erb (Duration: 5.9ms | Allocations: 2169)
Completed 200 OK in 65ms (Views: 58.7ms | ActiveRecord: 0.4ms | Allocations: 12682)
Started PUT "/users" for ::1 at 2019-09-01 07:52:08 +0900
Processing by Users::RegistrationsController#update as HTML
Parameters: {"authenticity_token"=>"86/7SxntwXMG/OAbh+AAn68awpo1aVR+Od0jVNX6Y5dZxZYA5w3+Y0AG48nsNXeTZ9vPd2UFersMQvdCwHJt5A==", "user"=>{"name"=>"新しいユーザー", "email"=>"hogehoge2@gmail.com", "d"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Update"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 3], ["LIMIT", 1]]
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
DEPRECATION WARNING: update_attributes is deprecated and will be removed from Rails 6.1 (please, use update instead) (called from update_without_current_password at /Users/#name/environment/products/book_give_app/app/models/user.rb:20)
(0.1ms) begin transaction
↳ app/models/user.rb:20:in `update_without_current_password'
User Update (0.6ms) UPDATE "users" SET "encrypted_password" = ?, "updated_at" = ? WHERE "users"."id" = ? [["encrypted_password", "$2a$11$1ZxOSTLooRXB7jAj4xyV1eyYUG1NZPQ93It8.AKYsVQvgGhgX22YG"], ["updated_at", "2019-08-31 22:52:08.883913"], ["id", 3]]
↳ app/models/user.rb:20:in `update_without_current_password'
(2.0ms) commit transaction
↳ app/models/user.rb:20:in `update_without_current_password'
Redirected to http://localhost:3000/
Completed 302 Found in 547ms (ActiveRecord: 3.2ms | Allocations: 187586)
パラメーターのところを見ると、passwordのところが何故か、"d"=>"[FILTERED]"
になっていますが全く心当たりがありません。
何かご教授頂けますと幸いです。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
まだ回答がついていません
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.35%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正の依頼
winterboum
2019/08/31 21:08
password更新時のlogを
tat_23
2019/09/01 08:06
追記依頼ありがとうございます、追記が完了いたしました。
よろしくお願い致します。
winterboum
2019/09/01 13:07
はて、、、、、
UPDATEしてるのに、BEGIN、COMMIT、ROLLBACKがない? そか、SQLレベルのlogは取っていないのか、
1) "d"=>"[FILTERED]" はおかしいですね。
1-1) "password"が渡っていないとすると、confirmと不一致というエラーになるはずが、それ出ていない
1-2) <div class="form-group">
<%= f.password_field :password, autocomplete: "new-password" ,:placeholder => "password",
id: "password", class: "form-control"%>
<small class="form-text password_help_text">(6文字以上) パスワードの変更が不要な場合は空欄のままUpdateボタンを押してください</small>
</div>
にあたる htmlでnameどうなってますか?
tat_23
2019/09/01 13:44
ご返信ありがとうございます、その部分を要素の検証で確認してみると、
<input autocomplete="new-password" placeholder="password" id="password" class="form-control" type="password" name="user[password]">
というようにnameは"user[password]"となっています...!!
winterboum
2019/09/01 14:32
合ってますね、、、
tat_23
2019/09/01 16:35
ですよね...泣
winterboum
2019/09/01 17:07
rspec とか minitest とかはやったことありますか?
User#update_without_current_password をきちんとテストしてみる