I use Bcrypt gem for password encryption.
User model:
class User < ApplicationRecord
has_secure_password
validates :password, presence: true, length: { minimum: 6 }, confirmation: true
# ...
end
How to allow password to be blank when user is updated?:
expect(user.update(name: 'Joana', password: '')).to be(true)
But not update password?
expect { user.update(name: 'Joana', password: '') }
.not_to(change { user.reload.password_digest })
If you want to test it, mind to find user before updating it not to get false positives:
user = User.find(user.id)
class User < ApplicationRecord
has_secure_password
validates(
:password,
allow_nil: { on: :update }, # add this
length: { minimum: 6 }
)
# ...
end
Thus these expectations pass:
user = User.find(user.id) # Refresh object as if you were in controller
expect(user.update(name: 'Joana')).to be(true)
expect(user.update(name: 'Joana', password: '')).to be(true)
expect { user.update(name: 'Joana', password: '') }
.not_to(change { user.reload.password_digest })
However, mind it would not update with actual nil
password:
expect(user.update(name: 'Joana', password: nil)).to be(false)
So, it is counter-intuitive but it works.
Confirmation, and presence validations are not needed as they're provided by Rails.