在功能规范中使用带有 has_secure_password 的 FactoryGirl 时出错

Error using FactoryGirl with has_secure_password in feature spec

如果相关,也使用 mongoid。

当我用factory girl创建用户时,它说用户是有效的。但是,当我通过 ActiveRecord 访问该用户时,却说它无效。以下是问题的概述:

user = create(:user, :activated)
user.valid? # => true
User.count # => 1
db_user = User.first
db_user == user # => true
db_user.valid? # => false
db_user.errors.count # => 0
# it only shows the error messages once I try to modify an attribute
db_user.email = "user@example.com"
db_user.save # => false
db_user.errors # => @messages={:password=>["is too short (minimum is 6 characters)", "can't be blank"]}

这是我的工厂:

FactoryGirl.define do
  factory :user do
    name { Faker::Name.name }
    email { "#{name.gsub(/[^0-9a-zA-Z]/i, '')}@example.com" }
    phone { Faker::Base.numerify("#{"#" * 10}") }
    admin false
    password "password"
    password_confirmation "password"
  end
end

这是用户模型的相关部分:

class User
  include Mongoid::Document
  include ActiveModel::SecurePassword

  field :name,              type: String
  field :email,             type: String
  validates :password, length: { minimum: 6 },
                      presence: true
  has_secure_password

您总是运行进行额外的验证。 has_secure_password 已经检查 password。所以你不需要存在验证。

您可以简单地使您的验证有条件

validates :password, length: { minimum: 6 }, if: Proc.new{|u| u.password_changed? }

我认为使用 ActiveModel::Dirty

应该可行

如果没有,您可以运行验证是否存在。

validates :password, length: { minimum: 6 }, if: Proc.new{|u| u.password.present? }

我决定看一下 Michael Hartl 的 "Rails Tutorial - Adding a secure password" 部分。看到他在has_secure_password之前写的代码是validates,如下图:

has_secure_password
validates :password, presence: true, length: { minimum: 6 }

尝试更改顺序,看看是否可行。我已经对它进行了测试,但这是我刚开始时使用的主要资源之一,过去它对我有用。祝你好运。

了解 has_secure_password 的内部工作原理很重要:

创建用户或更改其密码时,必须设置其 password(以及 – 根据配置 – password_confirmation)属性。但在内部 password 字段是 而不是 存储在数据库中,但它的值被散列并存储在名为 password_digest.

的数据库字段中

这意味着:当您从数据库加载现有用户时,其 password 属性将为 nil(但 password_digest 应该仍然存在)。因此,当您检查此类用户是否存在 password.

时,它将无效

为避免此问题,仅在创建新用户时验证密码是否存在,或者如果用户的 password 不是空白,这意味着用户尝试更新其密码:

# there must be a password on create
validates :password, presence: true, on: :create

# the password must follow conventions when present (of example on update)
validates :password, length: { minimum: 6 }, allow_blank: true