Validates_confirmation_of not working?

I just can’t get validates_confirmation_of working for the life of
me!..

It’s not the first time I’m having problems with it but I just never
understand why!.. This time I pretty much followed exactly the
example in Agile Rails Development and still…it just won’t work! I put
2 different passwords in the form and it doesn’t trigger an error,
nothign…

Here is my user model:

require ‘digest/sha1’

class User < ActiveRecord::Base

belongs_to :profile
belongs_to :company

validates_presence_of :username, :email, :address1, :city, :state,
:zip
validates_uniqueness_of :username, :email

attr_accessor :password_confirmation
validates_confirmation_of :password

validates_format_of :email, :with => /^[_a-z0
-9-]+(.[_a-z0-9-]+)@[a-z0-9-]+(.[a-z0 -9-]+)(.[a-z]{2,4})$/i

def validate
errors.add_to_base(“Missing Password”) if hashed_password.blank?
end

def self.authenticate(username, password)
user = self.find_by_username(username)
if user
expected_password = encrypted_password(password, user.salt)
if user.hashed_password != expected_password
user = nil
end
end
user
end

def password
@password
end

def password=(pwd)
@password = pwd
create_new_salt
self.hashed_password = User.encrypted_password(self.password,
self.salt)
end

private

def self.encrypted_password(password, salt)
string_to_hash = password + “wibble” + salt
Digest::SHA1.hexdigest(string_to_hash)
end

def create_new_salt
self.salt = self.object_id.to_s + rand.to_s
end
end

As you can see besides from a couple additional form, it’s pretty much
an exact copy of the suggested method in Agile Web D. with
Rails…

This is (part) of my view:

<% form_for :user, :url => {:action => ‘join’} do |f| %>

Pick a Password

<%= f.password_field :password %>


Confirm Password<br>
<%= f.password_field  :password_confirmation %>
<br><br>


<% end %>

Once again pretty straight forward…! What could be wrong?

Validations can all be run conditionally.

validates_confirmation_of :password, :on => :create

or

validates_confirmation_of :password,
:if=>Proc.new{|record|!record.password.blank?}

or various other ways.

Thanks for the tip! I can see how it can be an issue if
validates_confirmation_of is triggered when a record is updated…
however, in this case my problem is that validates_confirmation_of NEVER
triggers an error, even when my 2 password fields are different!..

If I can solve that issue first, then I’ll probably use your method to
fix the on create/on update issue, however, for now…well it won’t be a
problem since there’s no way I can get validates_confirmation_of to
trigger an error :wink:

Have you looked in the logs/development.log to see what your form is
passing in? You can also add a validates_presence_of
:password_confirmation to ensure that it is being passed in at all.

–Michael

I personally dislike validates_confirmation_of. Why? Because when I
UPDATE a model it triggers, even when I don’t want it to. However,
setting it to allow nil values doesn’t fix it – it makes it so the
value can be left blank!

I fought with this for a while, and came up with this method. What I
am doing is saying
that I only want to validate SOMETIMES. Other times I do not. The
times I do not are when it is not a new record and the password was
not provided.

I’m not certain if this allows someone to set their password to the
empty string or not…

Here’s the (probably gross) hack I’m doing:

validates_presence_of :password, :if => Proc.new { |u|
u.password_needed? }
validates_presence_of :password_confirmation, :if => Proc.new { |u|
u.password_needed? }
validates_length_of :password, :within => 4…40, :if => Proc.new {
|u| u.password_needed? }
validates_confirmation_of :password, :if => Proc.new { |u|
u.password_needed? }

def password_needed?
if new_record?
return true
end
if !password || password.empty?
return false
end
false
end

The :on => :create thing is CLOSE to what I want, but not quite there.
I do want to verify it if it is set and the record is not new, so the
proc thing probably works best.

–Michael

Michael G. wrote:

The :on => :create thing is CLOSE to what I want, but not quite there.
I do want to verify it if it is set and the record is not new, so the
proc thing probably works best.

–Michael

Makes sense…although right now…both ways aren’t really useful to me
as I can’t even get it to work hehe…

Do you (or anyone else) notice anything wrong in my model (the one I
posted in my first post) that could prevent validates_confirmation_of to
work??

Right now if I leave everything blank (so it triggers an error because
of the validates_presence_of)… and only fill both password fields
(with different values) and press submit, I’m taken back to the join
page (which is normal) with all the validations error (prensence_of and
formate_of basically) but nothing about the password/confirmation… and
the password filed is pre-filled with the value I had entered before,
but not the password_confirmation field…

If I add validates_presence_of :password_confirmation, I always get an
error saying it can’t be blank, even if I fill it…

Michael G. wrote:

Have you looked in the logs/development.log to see what your form is
passing in? You can also add a validates_presence_of
:password_confirmation to ensure that it is being passed in at all.

–Michael

I have these in the “parameters” in the development log:
… “password_confirmation”=>“kjdfdfg”, “password”=>“dfgdfs” …

Still, no errors were triggered…! (Well since I left all the other
required field blanks, some validates_presence_of errors were triggered)
but nothing about the password confirmation…

Those are the errors I got on the form:
7 errors prohibited this user from being saved

There were problems with the following fields:

* Address1 can't be blank
* City can't be blank
* Zip can't be blank
* Username can't be blank
* State can't be blank
* Email is invalid
* Email can't be blank

But…nothing about password/password confirmation

Thanks for the tip Michael!.. I found the problem thanks to the console
:slight_smile:

I realized that it was working (just like your example) in the console,
so I knew that the error wasn’t in the model!..It was actually in the
controller!

I was never assigning any values to @user.password_confirmation…I
added:
@user.password_confirmation = params[:user][:password_confirmation] to
the controller and it worked!..

Since password_confirmation wasn’t really a DB field, I just assumed I
didn’t had to assign any value to it…but I was wrong! :slight_smile:

So, now you have examples of the kinds of tests you should create,
both unit tests (so you know your model works) and controller tests
(so you know your controller works.)

:slight_smile:

–Michael

When I start hacking on problems like this, I usually narrow it down
as best I can.

In this case, I installed the AcriveRecord::BaseWithoutTable plugin,
so I could make a model that was not database backed:

ruby script/plugin install
http://svn.viney.net.nz/things/rails/plugins/active_record_base_without_table/

and made a simple model:

class Foo < ActiveRecord::BaseWithoutTable
attr_accessor :password
attr_accessor :password_confirmation

validates_presence_of :password
validates_presence_of :password_confirmation
validates_length_of :password, :within => 4…40
validates_confirmation_of :password
end

Here’s the script/console output:

x = Foo.new>> x = Foo.new
=> #<Foo:0x96e5448 @new_record=true, @attributes={}>

x.valid?
=> false

x.errors
=> #<ActiveRecord::Errors:0x96e4318
@errors={“password_confirmation”=>[“can’t be blank”], “password”=>[“is
too short (minimum is 4 characters)”, “can’t be blank”]},
@base=#<Foo:0x96e5448 @errors=#<ActiveRecord::Errors:0x96e4318 …>,
@new_record=true, @attributes={}>>

x.password = “123456”
=> “123456”

x.valid?
=> false

x.errors
=> #<ActiveRecord::Errors:0x96e4318
@errors={“password_confirmation”=>[“can’t be blank”]},
@base=#<Foo:0x96e5448 @password=“123456”,
@errors=#<ActiveRecord::Errors:0x96e4318 …>, @new_record=true,
@attributes={}>>

x.password_confirmation = “9876544”
=> “9876544”

x.valid?
=> false

x.errors
=> #<ActiveRecord::Errors:0x96e4318 @errors={“password”=>[“doesn’t
match confirmation”]}, @base=#<Foo:0x96e5448 @password=“123456”,
@errors=#<ActiveRecord::Errors:0x96e4318 …>, @new_record=true,
@attributes={}, @password_confirmation=“9876544”>>

x.password_confirmation = x.password
=> “123456”

x.valid?
=> true

See, you shouldn’t have to do any of that
If your form field is <%=password_field “user”, “password_confirmation”
%>

then this should be all handled for you when you do

@user = User.new(params[:user])

in your controller. You shouldn’t have to set it manually.