9

私のアプリでは、ユーザーは自分のプロフィール情報を編集できます。プロファイルの編集フォームで、ユーザーはすべてのフィールド (名前、役職など) を変更できます。current_passwordこの同じフォームには、 、password、およびの 3 つのフィールドがありpassword_confirmationます。bcrypthas_secure_passwordパスワード認証機能を利用しています。私はまったくDeviseを使用していません。

ユーザーが正しい現在のパスワードを提供した場合にのみパスワードを変更できるようにしたい。updateUsersコントローラーのメソッドで次のコードを使用して、これを以前に機能させました。

# 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
4

4 に答える 4