私のアプリでは、ユーザーは自分のプロフィール情報を編集できます。プロファイルの編集フォームで、ユーザーはすべてのフィールド (名前、役職など) を変更できます。current_password
この同じフォームには、 、password
、およびの 3 つのフィールドがありpassword_confirmation
ます。bcrypt
のhas_secure_password
パスワード認証機能を利用しています。私はまったくDeviseを使用していません。
ユーザーが正しい現在のパスワードを提供した場合にのみパスワードを変更できるようにしたい。update
Usersコントローラーのメソッドで次のコードを使用して、これを以前に機能させました。
# Check if the user tried changing his/her password and CANNOT be authenticated with the entered current password
if !the_params[:password].blank? && !@user.authenticate(the_params[:current_password])
# Add an error that states the user's current password is incorrect
@user.errors.add(:base, "Current password is incorrect.")
else
# Try to update the user
if @user.update_attributes(the_params)
# Notify the user that his/her profile was updated
flash.now[:success] = "Your changes have been saved"
end
end
ただし、このアプローチの問題は、現在のパスワードだけが正しくない場合に、ユーザー モデルへのすべての変更が破棄されることです。現在のパスワードが正しくない場合、すべての変更をユーザー モデルに保存したいのですが、パスワードの変更は保存したくありません。次のように IF ステートメントを分割しようとしました。
# Check if the user tried changing his/her password and CANNOT be authenticated with the entered current password
if !the_params[:password].blank? && !@user.authenticate(the_params[:current_password])
# Add an error that states the user's current password is incorrect
@user.errors.add(:base, "Current password is incorrect.")
end
# Try to update the user
if @user.update_attributes(the_params)
# Notify the user that his/her profile was updated
flash.now[:success] = "Your changes have been saved"
end
現在のパスワードが正しくなくても、ユーザーは自分のパスワードを変更できるため、これは機能しません。コードをステップ実行すると、「現在のパスワードが正しくありません。」にエラーが追加され@user
、メソッドを実行した後、update_attributes
このエラー メッセージは無視されるようです。
ちなみに、current_password
フィールドは User モデルの仮想属性です。
attr_accessor :current_password
私はこれを数時間理解しようとして立ち往生しているので、本当に助けを借りることができます.
ありがとう!
解決
papirtigerのおかげで、これが機能しました。彼の答えからコードを少し変更しました。以下は私のコードです。どちらのコード スニペットでも問題なく機能することに注意してください。
User モデル (user.rb) 内
class User < ActiveRecord::Base
has_secure_password
attr_accessor :current_password
# Validate current password when the user is updated
validate :current_password_is_correct, on: :update
# Check if the inputted current password is correct when the user tries to update his/her password
def current_password_is_correct
# Check if the user tried changing his/her password
if !password.blank?
# Get a reference to the user since the "authenticate" method always returns false when calling on itself (for some reason)
user = User.find_by_id(id)
# Check if the user CANNOT be authenticated with the entered current password
if (user.authenticate(current_password) == false)
# Add an error stating that the current password is incorrect
errors.add(:current_password, "is incorrect.")
end
end
end
end
そして、Users コントローラーのコードは単純になりました。
# Try to update the user
if @user.update_attributes(the_params)
# Notify the user that his/her profile was updated
flash.now[:success] = "Your changes have been saved"
end