# Custom Validations for ActiveRecord

**URL:** <https://www.ruby-forum.com/t/custom-validations-for-activerecord/66768>\
**Category:** Rails\
**Created:** [August 29, 2006, 4:13am UTC](https://www.ruby-forum.com/t/custom-validations-for-activerecord/66768 "2006-08-29T04:13:24Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![GreenRuby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/82dd89/32.png) [@GreenRuby](https://www.ruby-forum.com/u/GreenRuby)\
**Post date:** [August 29, 2006, 4:13am UTC](https://www.ruby-forum.com/t/custom-validations-for-activerecord/66768/1 "2006-08-29T04:13:24Z")

</div>

I want to create a model validation that ensures that the two passwords  
entered on the password creation page are equivalent. Sure I could put  
this into my controller but that wouldn’t be as clean. So I created two  
attributes in my model for the hashed password entries…

password\_hash and password1\_hash…

then I created a custom validation called validates\_equality\_of that  
takes three arguments - the two attributes to compare and a descriptor  
of what those attributes are for the error code.

Now I think I’m a genius…only problem is when the validator executes  
I get a run time error stating that my ‘errors’ variable is  
undefined…this should not happen. Can someone look at this snippet of  
code and tell me what I’ve done wrong?

require ‘digest/sha2’  
require ‘rubygems’  
require ‘breakpoint’  
require ‘logger’

module ActiveRecord  
module Validations  
module ClassMethods  
def validates\_equality\_of(attr1, attr2, description)  
$LOG.debug( “In validates\_equality\_of”) if $LOG != nil  
raise “description must be a string” if !description.is\_a?(  
String)  
if ( attr1 != attr2)  
$LOG.debug( “attributes not the same”) if $LOG != nil  
errors.add( attr2, “Both " + description + " must be the  
same”)  
else  
$LOG.debug( “Attributes the same”) if $LOG != nil  
end  
end  
end  
end  
end

class User \< ActiveRecord::Base  
validates\_uniqueness\_of :username  
validates\_equality\_of :password\_hash, :password1\_hash, “passwords”

def self.authenticate( username, password)  
user = User.find( :first, :conditions =\> [‘username = ?’,  
username])  
if user.blank? ||  
Digest::SHA256.hexdigest(password + user.password\_salt) !=  
user.password\_hash  
raise “Username or Password invalid”  
end  
user  
end

def password=(pass)  
$LOG.debug( “in password=”)  
if !self.password\_salt  
salt = [Array.new(6){rand(256).chr}.join].pack(‘m’).chomp  
self.password\_salt, self.password\_hash = salt,  
Digest::SHA256.hexdigest(pass + salt)  
else  
self.password\_hash = Digest::SHA256.hexdigest(pass +  
self.password\_salt)  
end  
end

def password1=(pass)  
$LOG.debug( “in password1=”)  
if !self.password\_salt  
salt = [Array.new(6){rand(256).chr}.join].pack(‘m’).chomp  
self.password\_salt, self.password1\_hash = salt,  
Digest::SHA256.hexdigest(pass + salt)  
else  
self.password1\_hash = Digest::SHA256.hexdigest(pass +  
self.password\_salt)  
end  
end

end

---

<div class="post-metadata">

**Author:** ![GreenRuby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/82dd89/32.png) [@GreenRuby](https://www.ruby-forum.com/u/GreenRuby)\
**Post date:** [August 29, 2006, 4:41am UTC](https://www.ruby-forum.com/t/custom-validations-for-activerecord/66768/2 "2006-08-29T04:41:31Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1

GreenRuby wrote:

> Now I think I’m a genius…only problem is when the validator executes  
> I get a run time error stating that my ‘errors’ variable is  
> undefined…this should not happen. Can someone look at this snippet of  
> code and tell me what I’ve done wrong?

You are saying ‘errors.add( … )’. You haven’t defined errors as a  
local variable so ruby is thinking you are calling a method.

You need to say @errors.add( … )’

Zach  
-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1.4.2.2 (GNU/Linux)  
Comment: Using GnuPG with Mozilla - [http://enigmail.mozdev.org](http://enigmail.mozdev.org)

iD8DBQFE86f/Myx0fW1d8G0RAkSlAJ95y8Ft2Fu7L3PIg6Rk8LoggH4LsgCcDz/I  
JPLuZhul7vqSFPjFFtgKqU8=  
=8x2g  
-----END PGP SIGNATURE-----

---

<div class="post-metadata">

**Author:** ![GreenRuby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/82dd89/32.png) [@GreenRuby](https://www.ruby-forum.com/u/GreenRuby)\
**Post date:** [August 29, 2006, 4:34am UTC](https://www.ruby-forum.com/t/custom-validations-for-activerecord/66768/3 "2006-08-29T04:34:14Z")

</div>

Can I ask why you’re not using built in validates\_confirmation\_of?  
Also check out the LoginEngine, the code should help.

---

<div class="post-metadata">

**Author:** ![GreenRuby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/82dd89/32.png) [@GreenRuby](https://www.ruby-forum.com/u/GreenRuby)\
**Post date:** [August 29, 2006, 4:49am UTC](https://www.ruby-forum.com/t/custom-validations-for-activerecord/66768/4 "2006-08-29T04:49:32Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1

- From my last post, rather the trying @errors.add( … ) try:  
record.errors.add( … )

Zach  
-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1.4.2.2 (GNU/Linux)  
Comment: Using GnuPG with Mozilla - [http://enigmail.mozdev.org](http://enigmail.mozdev.org)

iD8DBQFE86lLMyx0fW1d8G0RArNJAJ9mhIcNkQuheho43ePhBGDM996iNgCfXncJ  
HqlmyRKwWmNFWywUiiP/3tA=  
=gLye  
-----END PGP SIGNATURE-----

---

<div class="post-metadata">

**Author:** ![GreenRuby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/82dd89/32.png) [@GreenRuby](https://www.ruby-forum.com/u/GreenRuby)\
**Post date:** [August 29, 2006, 5:11am UTC](https://www.ruby-forum.com/t/custom-validations-for-activerecord/66768/5 "2006-08-29T05:11:34Z")

</div>

zdennis - that does not work - record is also not defined…

from what I can tell all the calls you can use to get a record in scope  
only work with one attribute at a time…

Still wondering…

---

<div class="post-metadata">

**Author:** ![GreenRuby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/82dd89/32.png) [@GreenRuby](https://www.ruby-forum.com/u/GreenRuby)\
**Post date:** [August 29, 2006, 6:05am UTC](https://www.ruby-forum.com/t/custom-validations-for-activerecord/66768/6 "2006-08-29T06:05:36Z")

</div>

GreenRuby wrote:

> Jonathan,you have a very good point…why is that not called  
> validates\_password or something equivalent…
> 
> I’m still interested in why my code doesn’t work…

Your code doesn’t work because it’s being run in the wrong context.  
You’re defining a class-level method that needs to be run in the  
instance context.

The validates\_\* methods don’t actually run the validation code - they  
generate code to be run when valid? is called. Basically, your method,  
instead of checking the record’s attributes and adding an error, should  
add a hook to be called on validation.

You could do:

validate do |record|  
record.errors.add(attr1, message) unless record.send(attr1) ==  
record.send(attr2)  
end

However, this sort of breaks the convetions the Rails validations tend  
to use, and isn’t really configurable. Have a look at validations.rb in  
the ActiveRecord source if you want to see how validations work.

---

<div class="post-metadata">

**Author:** ![GreenRuby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/82dd89/32.png) [@GreenRuby](https://www.ruby-forum.com/u/GreenRuby)\
**Post date:** [August 29, 2006, 5:13am UTC](https://www.ruby-forum.com/t/custom-validations-for-activerecord/66768/7 "2006-08-29T05:13:34Z")

</div>

Jonathan,you have a very good point…why is that not called  
validates\_password or something equivalent…

I’m still interested in why my code doesn’t work…
