16

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?

1
  • 1
    You can also update attributes using @user.update_attributes({}) or @user.update_attribute :attr_name, value. Commented Jun 7, 2012 at 8:36

2 Answers 2

21

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
Sign up to request clarification or add additional context in comments.

3 Comments

option 1 nice, just what I needed. But "password_validation" should be "password_confirmation".
!password.nil? is better then .present?, else signing up without password is possible
.present? returns true if the string is nil? or blank?, so it ensures that the string contains one or more characters apart from spaces.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.