我有以下用户模型:
class User < ActiveRecord::Base
# Users table has the necessary password_digest field
has_secure_password
attr_accessible :login_name, :password, :password_confirmation
validates :login_name, :presence=>true, :uniqueness=>true
# I run this validation on :create so that user
# can edit login_name without having to enter password
validates :password,:presence=>true,:length=>{:minimum=>6},:on=>:create
# this should only run if the password has changed
validates :password_confirmation,
:presence=>true, :if => :password_digest_changed?
end
这些验证并不完全符合我的希望。可以执行以下操作:
# rails console
u = User.new :login_name=>"stephen"
u.valid?
# => false
u.errors
# => :password_digest=>["can't be blank"],
# => :password=>["can't be blank", "please enter at least 6 characters"]}
# so far so good, let's give it a password and a valid confirmation
u.password="password"
u.password_confirmation="password"
# at this point the record is valid and does save
u.save
# => true
# but we can now submit a blank password from console
u.password=""
# => true
u.password_confirmation=""
# => true
u.save
# => true
# oh noes
所以我想要的是以下内容:
令我困惑的是,如果我在password_confirmation验证中使用password_changed?
而不是:password_digest_changed?
,则rails会抛出无方法错误。我不明白为什么。
所以有人知道我在这里做错了吗?
答案 0 :(得分:13)
password
不是数据库中的列,对吧?只是一个属性?
因此没有password_changed?
方法,如果password
是一列,则该方法可用。相反,您应该检查是否设置了password
。
类似的东西:
validates :password_confirmation, :presence => true, :if => '!password.nil?'
虽然这解决了您遇到的最初问题,但它仍然不会完全按照您的意愿行事,因为它只是检查状态,您需要它存在和匹配密码。以下内容应该有效(与上述验证相结合)。
validates :password,
# you only need presence on create
:presence => { :on => :create },
# allow_nil for length (presence will handle it on create)
:length => { :minimum => 6, :allow_nil => true },
# and use confirmation to ensure they always match
:confirmation => true
如果您之前从未见过:confirmation
,那么这是一个标准验证,可以查找foo
和foo_confirmation
,并确保它们是相同的。
请注意,您仍需要检查是否存在password_confirmation