views:

743

answers:

3

I have a User model with the usual attributes such as email and hashed_password etc. I want to write a validation that checks for the presence of an email address but only when

1) there isn't one stored in the database for this object (i.e. this is a new user signing up)

2) the user is trying to update their email address.

My current validations

  validates_presence_of :email
  validates_presence_of :email_confirmation

  validates_confirmation_of :email

are obviously preventing me from updating any attributes. I thought of using

validates_presence_of :email , :if :email_validation_required?

def email_validation_required?
self.email.blank?
end

But that wont help with scenario 2 as it will return true because the user does have an password email address in the db.

I cant work out how i can limit it to just those 2 scenarios above.

Can anyone help?

+2  A: 

you have two options. one is to use :on. by default, they are set to :on => :save, but you can do something like this this

validates_presence_of :email, :on => :create

or

validates_presence_of :email, :on => :update

the other options is to use :if, and then pass in a method name or a proc. so something like

validates_presence_of :email, :if => :should_validate

or

validates_presence_of :email, :if => Proc.new { |user| user.signup_stage > 2 }

Hope that helps :)

Matt Briggs
hi matt thanks for you help. I had thought of using a method with :if but got stumped on how to writ the logic inside it. I was wondering if there was a way without having to introduce more attributes to my model. I notice in your last example you mention a signup_stage attribute.
adam
I was just giving rather generic examples. On re-reading your question, why will the email be blank in your model if the user has a password in the db?
Matt Briggs
sorry that password was a typo - it should have read email. Edited the post.
adam
+1  A: 

You want to use an :if clause on the validation that uses the ActiveRecord::Dirty methods:

validates_presence_of :email, :if => Proc.new { |user| user.email_changed?}

N.B. Only works in Rails 2.1 or later.

EmFi
+1  A: 

I think EmFi is on to something. But I don't think the validates_presence_of :email should be holding you up. The email should always be present - if it is left blank in the form the parameter will not mess with your save of the user. If it is entered in the form, even for update, it should have an email_confirmation along for the ride.

Give this a try:

validates_presence_of :email
validates_presence_of :email_confirmation, :if => :email_changed?

validates_confirmation_of :email
Barry Hess
sorry for the late reply barry, your right about it not holding me up. I was just replicating the code for password_confirmation for email_confirmation but that has different requirements. Thanks for pointing it out.
adam