【发布时间】:2013-09-26 08:25:23
【问题描述】:
我不确定如何最好地解决此问题 - 添加新记录时我需要验证用户的密码,并且我还需要能够在更新密码时进行验证。但是我怎样才能让用户只更新他们的部分个人资料,并可能将密码留空。
注意在您建议 allow_blank 之前,我知道此选项,但这不合适,因为当用户因丢失/忘记密码而需要更改密码时,我不想允许用户密码为空。
【问题讨论】:
标签: ruby-on-rails validation ruby-on-rails-4
我不确定如何最好地解决此问题 - 添加新记录时我需要验证用户的密码,并且我还需要能够在更新密码时进行验证。但是我怎样才能让用户只更新他们的部分个人资料,并可能将密码留空。
注意在您建议 allow_blank 之前,我知道此选项,但这不合适,因为当用户因丢失/忘记密码而需要更改密码时,我不想允许用户密码为空。
【问题讨论】:
标签: ruby-on-rails validation ruby-on-rails-4
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 设置为 nil。由于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_digest)。
【讨论】:
if password or password_confirmation 将避免验证字段,如果没有提供。 validates_presence_of :ashed_password 在从未提供过密码的情况下如果不提供密码将触发错误。对于 reset_password,只需在操作中将 #hashed_password 设置为 nil,然后再尝试保存记录。
if password or password_confirmation 在这两种情况下都会被忽略 - 我需要在 Rails4 中使用 attr_accessor 吗?