Forum: Ruby on Rails How to skip password validation when updating other fields?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
F1a41eb20260a0f7442a00c70595e512?d=identicon&s=25 JJ (Guest)
on 2006-03-29 23:20
Besides the hashed password, which is saved to db, I have two
password-attributes in my User model:

attr_accessor :password, :password_confirmation

I have validations on these attributes, and I need them to work both on
create and update, since I have pages for changing and resetting the
password.

Now when I want to update just the user's login name, I guess I have the
next options:

1)
user = User.find(session[:user_id])
user.login = params[:login]
user.save
=> Won't work because the password and password_confirmation validations
hit.

2)
user = User.find(session[:user_id])
user.login = params[:login]
user.update_attributes(:login => params[:login] )
=> Won't work because the password and password_confirmation validations
hit.


3)
user = User.find(session[:user_id])
user.login = params[:login]
user.update_attribute(:login, params[:login] )
=> Updates the fiels to db, but passes all validations. Now I think it's
bad idea to do the validations every time in the controller when I need
to update a field.

4)
user = User.find(session[:user_id])
user.login = params[:login]
if user.valid?
  user.update_attribute(:login, params[:login] )
end
=> Won't work because the password and password_confirmation validations
hit.

Is there any way to skip the validations for the password attributes?

I've been thinkin of creating validation method in the user model, that
skips the password-fields like this:

def validate_all_but_password
 loop through validations
   if the validation name doesn't equal 'password' or
'password_confirmation'
     run the validation

and then call it before update_attribute.

What do you think, would this be a good practise, or is there another
way to solve this problem?
F1a41eb20260a0f7442a00c70595e512?d=identicon&s=25 JJ (Guest)
on 2006-03-30 00:19
If I just had surfed to the api doc before posting... heh

Found the solution, added this on the validations of password:

:if  => :validate_password

then before I call user.save I call user.dont_validate_password, which
sets instance variable to false and the validate_password method then
returns false.
A9d77f57187ac17ae968d8bd2186d4ad?d=identicon&s=25 Don Walker (walkins)
on 2006-03-30 00:21
(Received via mailing list)
How about specifying that the validation only be performed upon model
creation?

E.g. validates_confirmation_of :password, :password_confirmation, :on =>
:create
F1a41eb20260a0f7442a00c70595e512?d=identicon&s=25 JJ (Guest)
on 2006-03-30 00:38
Don Walker wrote:
> How about specifying that the validation only be performed upon model
> creation?
>
> E.g. validates_confirmation_of :password, :password_confirmation, :on =>
> :create

But I need to validate the input also when the user updates the
password.
6ef8cb7cd7cd58077f0b57e4fa49a969?d=identicon&s=25 Brian Hogan (Guest)
on 2006-03-30 01:01
(Received via mailing list)
Basically, you just have to look at the before_create and before_save
methods.

Here's what I do... Password field is validated on create only.
Password is set on update only if the password field is not nil.

class User < ActiveRecord::Base
  attr_accessor :password
  attr_accessible :username, :password, :email
  validates_uniqueness_of :username, :email
  validates_presence_of :username, :email
  has_and_belongs_to_many :machines

  #
  def validate_on_create
    errors.add_to_base("Password field must not be left blank!") if
self.password == "" or self.password.nil?
  end

  # hash the password for storage in the DB
  def before_create
    self.hashed_password = User.hash_password(self.password)
  end

  # hash the password before updating but only if the password field is
actually filled in.
  def before_update()
    unless self.password.nil?
      self.password = User.hash_password(self.password)
    end
  end

  def after_create
    self.password = nil
  end

end
C31c7255fa4488dfc5d766403b497a36?d=identicon&s=25 Jim Morris (wolfmanjm)
on 2006-03-30 01:01
(Received via mailing list)
You could do it this way in your model...

    validates_presence_of :password, :if => :password_required?
    validates_confirmation_of :password, :if => :password_required?

where...

protected
   def password_required?
        hashed_password.blank? or not password.blank?
    end
This topic is locked and can not be replied to.