Modeling 'phony' fields

Hi,

I have a user model with an e-mail field. When a user registers for the
site, I want them to confirm their email address by typing it in again.
If they change their email address, I want them to confirm their email
address by typing it in again. However, the user might change things on
their account not related to their email address, such as their phone
number, and they should not have to confirm their email address.

I suppose I can add an email_confirmation field to the database, and
then use

validates_confirmation_of :email

But, this seems rather wasteful and silly to store both the email and
the email_confirmation. I understand that the model need not store the
field in the database, but then in that case User.find(:first) …
fiddle with attributes other than email address … User.save (rightly)
throws an error because the email_confirmation field doesn’t match
email.

What is the proper way to model a phony email_confirmation field, such
that confirmation validation is only fired when the e-mail address is
actually updated?

Thank you.

Regards,

Rich

You don’t need to make a database field for the email_confirmation,
you can use it simply by including:

validates_confirmation_of :email

Rails handles the creation of a virtual attribute for you.

What is the proper way to model a phony email_confirmation
field, such that confirmation validation is only fired when the
e-mail address is actually updated?

Sorry hit reply before including the rest of my reply

validates_confirmation_of :email
:if => :change_email?

def change_email?

make sure that the user requested an email change

end

You don’t need to make a database field for the email_confirmation,
you can use it simply by including:

validates_confirmation_of :email

Yes, that’s where I started. However, when I need to update something
completely unrelated, the email confirmation rule gets in the way:

user = User.find(1)
user.update_attributes(:contact_by_phone => true) => false
user.errors.each_full { |msg| puts msg } => ‘Email confirmation can’t be
blank’

So, how can I structure the email confirmation rule to only fire when
the email address is changing, either through the creation of a new
user, or a request to actually update the email address?

Thank you.

Regards,
Rich

validates_confirmation_of :email
:if => :change_email?

def change_email?

make sure that the user requested an email change

end

Hi Jim,

This is getting to the crux of the issue. I am looking for the right
way to implement just such a ‘change_email?’ function.

In my view, I want to display the current e-mail address, and allow the
user to type over it if they choose. So, I currently use
<% form_for :user, @user do |f| -%>

(and so on)

When the record is retrieved from the db, of course the email field is
filled. The confirmation is not:
user = User.find(1)
user.email
[email protected]
user.email_confirmation
nil

And therefore .save will not complete because user.email and
user.email_confirmation don’t match.

This makes perfect sense, as there is no database field for
email_confirmation. So, perhaps I ought to initialize
user.email_confirmation = user.email when a record is created or
retrieved? I’m not sure how…but then the validation should always
work, even if nothing gets changed.

Or, somehow, I would need to compare the email stored in the db to a
different email field that comes back from the form. Perhaps I should
add an email_new accessor to the model, and then the view points to it?
I would still need to initialize email_new with the current value of
email, I guess.

Anyway, this is why I wrote the list to begin with. Not sure how to
deal with the ‘phony’ confirmation fields.

Thank you.

Regards,
Rich

Email * <%= f.text_field :email %>
Confirm Email * <%= f.text_field :email_confirmation %>

This is getting to the crux of the issue. I am looking for the right
way to implement just such a ‘change_email?’ function.

In my view, I want to display the current e-mail address, and allow
the

different email field that comes back from the form. Perhaps I should
add an email_new accessor to the model, and then the view points to
it?

Well, for the archives, I did the following:

class User < ActiveRecord::Base

validates_confirmation_of :email

def after_find
self.email_confirmation = self.email
end
end

This way, any new or changing email addresses cause the
validates_confirmation_of to fire, and, in cases where other things are
getting updated, such as

user = User.find(1)
user.update_attributes(:contact_by_phone => false)
user.save

The validation will operate successfully.

Thanks.

Regards,
Rich

In theory (i.e. untested). You could store the existing email address
in an after_initialize handler. Then, in a before_save (or maybe
before_validate?) handler, you could check if the email was different.
If so, you could manually add errors to the object to prevent it from
being saved.

Does that make sense?

Chris

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs