2

Hello I trying to create a reset password for my rails app; but when I try to save I get the following error:

Validation failed: Password can't be blank, Password is too short (minimum is 6 characters), Password confirmation can't be blank

This is my user model.

class User < ActiveRecord::Base
  attr_accessible :email, :password, :password_confirmation
  has_secure_password

  before_save { |user| user.email = email.downcase }
  before_save :create_remember_token

  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
  validates :password, presence: true, length: { minimum: 6 }
  validates :password_confirmation, presence: true

    def send_password_reset
        self.password_reset_token = SecureRandom.urlsafe_base64
        self.password_reset_at = Time.zone.now
        self.password = self.password
        self.password_confirmation = self.password
        save!
    end

  private

    def create_remember_token
        self.remember_token = SecureRandom.urlsafe_base64
    end

end

the method "send_password_reset" doesn't update the user and I don't understand why is trying to save the user instead on updating just password_reset_token and the password_reset_at.

Does anybody can help me, please?

Jean
  • 5,201
  • 11
  • 51
  • 87

1 Answers1

8

When you call save! on the model instance, it's going to run the validations on your User model; all of them.

There are a number of ways to skip the password validations conditionally. One is to use a Proc

validates :password, presence: true, length: { minimum: 6 }, unless: Proc.new { |a| !a.new_record? && a.password.blank? }

This will allow the User instance to be saved and will skip the validation of the :password field if it's blank and the User is not new (already persisted to the database).

Here is most of a password validation I use in my applications

validates :password, confirmation: true,
                     length: {:within => 6..40},
                     format: {:with => /^(?=.*\d)(?=.*([a-z]|[A-Z]))([\x20-\x7E]){6,40}$/},

Notice, you don't need the separate validation on :password_confirmation. Instead just pass confirmation: true to the :password validator.

Suggested Reading:

deefour
  • 34,974
  • 7
  • 97
  • 90
  • Thank you very much. I'm going to accept your answer, but stackoverflow said that I have to wait 5min. – Jean Oct 28 '12 at 19:50