validates_confirmation_of not working?

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

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.

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

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

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

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

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.