*** Disclaimer: I am new to rails myself. ***
if I ever attempt something like this in my User unit tests…
user = users(:user_jeff)
assert user.valid?
I will get an assertion failure like this:
‘Password is too short (minimum is 6 characters)’
Any suggestions as to what I SHOULD be doing?
I’m not sure what the “best practice” way of doing it is, but I was
coming up
against the same problem recently myself. I will probably eventually
use one
of the popular user management generators, but I wanted to implement it
myself first, so that I understood properly the issues involved. I
don’t
have time right now to give a detailed explanation of how I handled it,
but
the gist of it is this:
I created a separate Password class that was responsible for handling
all
password functionality. This class could be initialized either via the
hashed password and salt (for when it is initialized from the database),
or
by passing it a plain text password. Rather than doing a
“validates_length_of :password” in the user model, I did
##############
def validate
errorString = @password.validation_errors
if errorString then
errors.add :password, errorString
end
end
##############
where @password is an instance of my Password class. So the Password
class
does the actual validation in validation_errors(). If it is initialized
with
the password hash, it will assume that everything is ok, and return nil
from
validation_errors (the user class does not allow the password_hash or
password_salt to be set by a params hash). If it was initialized from a
plaintext password, it will check that everything is ok, and return an
error
string if anything is wrong. This way, errors are checked when the
password
is first stored, but you won’t get spurious errors when the password
info is
loaded from the database.
I also have (in my User model)
##############
before_save :encrypt_password
def encrypt_password
self.password_hash, self.password_salt =
@password.encrypted_version
end
##############
Hmm, it seems that I have given a reasonably detailed explanation after
all.
Let me know if you need more clarification though (there were a couple
of
other things I had to do… I had to add the following functions to User
as
well; let me know if you need me to explain why):
##############
protected
# This is only called when explicitly creating an object,
# not when it is pulled from the database
def initialize(*params)
@password = Password.new(nil, nil)
super
end
# This is called regardless of whether the object
# is explicitly created or not.
def after_initialize
@password ||= Password.new(self.password_hash,
self.password_salt)
end
##############
Oh, and if anyone thinks I’ve done something stupid, let me know too…
(see
disclaimer at the beginning of this mail
)
Michael.