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

时间:2016-07-20 15:50:03

标签: ruby-on-rails ruby rspec mongoid factory-bot

如果相关,也使用mongoid。

当我使用工厂女孩创建用户时,它表示用户有效。但是,当我通过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

3 个答案:

答案 0 :(得分:0)

您始终在运行其他验证。 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? }

答案 1 :(得分:0)

我决定看看Michael Hartl的"Rails Tutorial - Adding a secure password"部分。我看到他在 has_secure_password之前使用validates 编写了代码,如下所示:

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

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

答案 2 :(得分:0)

了解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