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.
JJ (Guest)
on 2006-03-30 01: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?
JJ (Guest)
on 2006-03-30 02: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.
Don W. (Guest)
on 2006-03-30 02: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
JJ (Guest)
on 2006-03-30 02: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.
Brian H. (Guest)
on 2006-03-30 03: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
Jim M. (Guest)
on 2006-03-30 03: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.