0

我不确定如何最好地解决这个问题 - 添加新记录时我需要验证用户的密码,并且我还需要能够在更新密码时进行验证。但是我怎样才能让用户只更新他们的个人资料的一部分,并可能将密码留空。

在您建议 allow_blank 之前请注意,我知道此选项,但这不合适,因为当用户因丢失/忘记密码而需要更改密码时,我不想让用户拥有空白密码。

4

3 回答 3

2
validates :password, presence: true, if: lambda { |user| user.password_changed? }

by ActiveModel::Dirty (默认适用于所有模型)

于 2013-09-26T10:13:40.630 回答
1

您可以将 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 并且不会触发验证。

于 2013-09-26T08:35:12.410 回答
1

完全自定义方式

通常,#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

创建用户时提供密码、虚拟属性passwordpassword_confirmation设置,因此if条件为真并强制执行验证。

当密码已经设置并且用户没有更改它(没有提供密码的编辑表单)时,将不会强制执行验证,因为if password and password_confirmation.

当密码已经设置并且用户更改它passwordpassword_confirmation设置时,就会触发验证。

当您想重置密码时,只需在您的操作hashed_password中设置为零。该模型现在无效,因为validates_presence_of :hashed_password用户必须提供一个新模型。

使用 #has_secure_password

使用#has_secure_password,rails 将处理大部分情况,尤其是:

  • 它创建虚拟属性
  • 仅当提供密码属性时才会触发确认匹配验证
  • 它将散列密码

因此,您需要的只是添加您自己的验证,仅在存在passwordpassword_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)。

于 2013-09-26T08:46:14.147 回答