wgpubs
wgpubs

Reputation: 8261

How to disable password/confirmation validations when using has_secure_password in Rails 3.2?

I have a user model set up as such:

class User < ActiveRecord::Base
  has_secure_password

  # callbacks -------------------------------------------------------------------------
  before_create { generate_token(:auth_token) }

  # setup accessible (or protected) attributes for your model and validation ----------
  attr_accessible :email, :password, :password_confirmation

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

  validates :password             , length: { minimum: 6 } 

  validates :password_confirmation, presence: true

But I don't want the password and/or password_confirmation validations to run when updating the user unless the user is attempting to change their password.

So, if the user updates their information in a form without specifying a password and/or confirmation it should succeed. If the user updates their information and includes a password and/or confirmation the validations should run.

What is the best way to accomplish this?

Upvotes: 16

Views: 4910

Answers (2)

thde
thde

Reputation: 115

In addition to Zabba's answer, option 1 could also be written like this:

with_options if: :password_provided? do
    validates :password, :password_confirmation, presence: true, length: { minimum: 12 }
end

def password_provided?
    password.present? || password_confirmation.present?
end

Upvotes: 0

Zabba
Zabba

Reputation: 65457

You could add a conditional :if to both validators:

Option 1:

validates :password             , length: { minimum: 6 }, :if => :validate_password?
validates :password_confirmation, presence: true        , :if => :validate_password?

def validate_password?
  password.present? || password_confirmation.present?
end

Option 2:

Or use a method for validation, moving the validation checks into the method instead of as separate validates calls:

validate :check_password, :on => :update

def check_password
  return unless password.present? || password_confirmation.present?
  ..validations for both attributes here.. 
  ..check presence, length etc. as required and add to the errors variable as necessary..
end

Upvotes: 21

Related Questions