我不确定如何最好地解决这个问题 - 添加新记录时我需要验证用户的密码,并且我还需要能够在更新密码时进行验证。但是我怎样才能让用户只更新他们的个人资料的一部分,并可能将密码留空。
在您建议 allow_blank 之前请注意,我知道此选项,但这不合适,因为当用户因丢失/忘记密码而需要更改密码时,我不想让用户拥有空白密码。
我不确定如何最好地解决这个问题 - 添加新记录时我需要验证用户的密码,并且我还需要能够在更新密码时进行验证。但是我怎样才能让用户只更新他们的个人资料的一部分,并可能将密码留空。
在您建议 allow_blank 之前请注意,我知道此选项,但这不合适,因为当用户因丢失/忘记密码而需要更改密码时,我不想让用户拥有空白密码。
validates :password, presence: true, if: lambda { |user| user.password_changed? }
by ActiveModel::Dirty (默认适用于所有模型)
您可以将 if 语句传递给验证:
`validates_presence_of :password, :if => :should_validate_password?
您应该能够在这里传递一个条件来捕捉用户是否正在更新他们的密码:
模型
def should_validate_password?
updating_password || new_record?
end
控制器
@user.updating_password = true
@user.save
有关更多详细信息,请参见此处:http ://railscasts.com/episodes/41-conditional-validations
更新:
在您的情况下,我将在控制器中创建一个 if 语句,以检测参数中是否传递了任何新密码。如果是这样,我会设置@user.updating_password = true
哪个会触发模型中的验证。如果不是,那么@user.updating_password
将是 nil 并且不会触发验证。
通常,#password=
并且#password_confirmation=
只是虚拟设置器,真正的属性是 #hashed_password
什么。所以,你可以做这样的事情:
class User
attr_accessor :password, :password_confirmation
validate :validates_password
validates_presence_of :hashed_password
private
def validates_password
if password or password_confirmation
if password != password_confirmation
errors.add( :password, 'your message' )
end
# your others validations
self.hashed_password = hash_password
end
end
def hash_password
# your hashing code
end
end
创建用户时提供密码、虚拟属性password
并password_confirmation
设置,因此if
条件为真并强制执行验证。
当密码已经设置并且用户没有更改它(没有提供密码的编辑表单)时,将不会强制执行验证,因为if password and password_confirmation
.
当密码已经设置并且用户更改它password
并password_confirmation
设置时,就会触发验证。
当您想重置密码时,只需在您的操作hashed_password
中设置为零。该模型现在无效,因为validates_presence_of :hashed_password
用户必须提供一个新模型。
使用#has_secure_password
,rails 将处理大部分情况,尤其是:
因此,您需要的只是添加您自己的验证,仅在存在password
或password_confirmation
存在时进行。
class User
has_secure_password
validate :validates_password
private
def validates_password
if password or password_confirmation
unless <your_test>
errors.add( :password, '<your error message>' )
end
end
end
end
如前所述,只有在提供了 password 和 password_confirmation 时才会触发,只有当用户将它们作为表单数据提交时才会发生这种情况(因为真实属性是password_digest
)。