我从头开始有一个身份验证系统,当用户点击“编辑个人资料'无论他想编辑哪个字段,都必须输入当前密码。
def update
if params[:user][:password].present?
authenticated = @user.authenticate(params[:user][:current_password])
if authenticated && @user.update(user_params)
redirect_to root_url
flash[:notice] = "Your profile was successfully updated!"
else
@user.errors.add(:current_password, 'is invalid') unless authenticated
render :edit
end
elsif @user.update(user_params)
redirect_to root_url
flash[:notice] = "Your profile was successfully updated!"
else
render :edit
end
end
如何仅在用户想要更改密码的情况下调用身份验证或使用某些上下文模型验证?
答案 0 :(得分:1)
我不建议将此逻辑混合到模型中,因为随着应用程序的增长,最终会出现难以遵循的复杂性。
尝试查看表单对象:
我实现了这样的事情:
class UserUpdateForm
include ActiveModel::Model
# Attributes
attr_accessor :user, :new_password, :new_password_confirmation
# Validations
validates :current_password, if: :new_password
validate :authenticate, if: :current_password
validates :new_password, confirmation: true, allow_blank: true
def initialize(user)
self.user = user
end
def submit(params)
self.new_password = params[:new_password]
self.new_password_confirmation = params[:new_password_confirmation]
if self.valid?
# Set other attributes as needed, then set new password below.
self.user.password = self.new_password if self.new_password.present?
self.user.save
else
false
end
end
private
def authenticate
unless self.authenticate(self.current_password)
self.errors.add(:current_password, 'is invalid')
end
end
end
然后您可以从控制器中调用它,如下所示:
def update
@user_update_form = UserUpdateForm.new(@user)
if @user_update_form.submit(params)
flash[:notice] = "Your profile was successfully updated!"
redirect_to root_url
else
render :edit
end
end
请参阅上面的链接,了解如何处理视图等。这只是为了让你开始。
答案 1 :(得分:0)
您可以在此操作语句中创建嵌套的if-else,以检查new_password
是否存在new_password_confirmation
和params[:user]
(或者调用新密码和确认字段){{1}对象。如果它们存在 - 您可以重定向到某个页面王,并要求输入现有密码。
另一种方法是使用ajax以异步方式显示具有相同请求的对话框(例如,处理该问题的respond_with自调用javascript函数)。然后在控制器的其他操作中处理对话框中的提交按钮。
更新(考虑使用验证器):
考虑到验证,您可以编写自己的validator(用于密码)和条件,以检查新密码字段何时附带来自客户端的一些数据。
我认为它看起来像这样:
validate :password_update?
def password_update?
if new_password.present?
if current_password !== self.password
errors.add(:current_password, "must be supplied!")
else
# update data and password
end
else
# do your regular update
end
end