From be6a6b92b15dd17ba4053a9a6e44676c329c355d Mon Sep 17 00:00:00 2001 From: Stijn Mathysen Date: Sat, 20 Dec 2008 13:15:08 +0100 Subject: [PATCH] added a validator for email addresses --- activerecord/lib/active_record/validations.rb | 26 ++++++++++++++++++++ activerecord/test/cases/validations_test.rb | 32 ++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletions(-) diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index 617b3f4..9e43cf0 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -801,6 +801,32 @@ module ActiveRecord end end + # Validates whether the value of the specified attribute is a valid email address. + # + # class Person < ActiveRecord::Base + # validates_email :email + # end + # + # Configuration options: + # * :message - A custom error message (default is: "is invalid"). + # * :on - Specifies when this validation is active (default is :save, other options :create, :update). + # * :if - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). + # The method, proc or string should return or evaluate to a true or false value. + # * :unless - Specifies a method, proc or string to call to determine if the validation should + # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). + # The method, proc or string should return or evaluate to a true or false value. + def validates_email(*attr_names) + configuration = { :on => :save } + configuration.update(attr_names.extract_options!) + + validates_each(attr_names, configuration) do |record, attr_name, value| + unless value =~ /\A[\w!#\$%&'*+\/=?^`{|}~-]+(?:\.[\w!#\$%&'*+\/=?^`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum)\Z/i + record.errors.add(attr_name, :invalid, :default => configuration[:message], :value => value) + end + end + end + # Validates whether the value of the specified attribute is available in a particular enumerable object. # # class Person < ActiveRecord::Base diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb index 380d8ac..e971bdb 100644 --- a/activerecord/test/cases/validations_test.rb +++ b/activerecord/test/cases/validations_test.rb @@ -558,7 +558,7 @@ class ValidationsTest < ActiveRecord::TestCase assert w6.errors.on(:city), "Should have errors for city" assert_equal "has already been taken", w6.errors.on(:city), "Should have uniqueness message for city" end - + def test_validate_format Topic.validates_format_of(:title, :content, :with => /^Validation\smacros \w+!$/, :message => "is bad data") @@ -618,6 +618,36 @@ class ValidationsTest < ActiveRecord::TestCase assert_equal "can't be Invalid title", t.errors.on(:title) end + def test_validate_email + Topic.validates_email(:title, :content, :message => 'thats not a real email address, is it?') + + t = Topic.create('title' => 'stijn@skylight.be', 'content' => 'stijn@blah.blah') + assert !t.valid?, "Shouldn't be valid" + assert !t.save, "Should't save because content is not valid" + assert_nil t.errors.on(:title) + assert_equal 'thats not a real email address, is it?', t.errors.on(:content) + + t.content = '.mail@mail.com' + + assert !t.valid?, "Shouldn't be valid" + assert !t.save, "Should't save because a mail address cannot start with a dot" + assert_equal 'thats not a real email address, is it?', t.errors.on(:content) + + t.content = 'mail.@mail.com' + + assert !t.valid?, "Shouldn't be valid" + assert !t.save, "Should't save because a mail address cannot end with a dot" + assert_equal 'thats not a real email address, is it?', t.errors.on(:content) + + t.content = "|e!v#e$r%y&s'p*e+c-i/a=l?c^h_a`r{a|c}t~e.r@that-is.allowed.gov" + assert t.save + assert_nil t.errors.on(:content) + + t.content = 'elisabeth_post@about.a.museum' + assert t.save + assert_nil t.errors.on(:content) + end + def test_validates_inclusion_of Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ) ) -- 1.5.4.5 From 76822905698af4fe7369afc3619548c8bfd318ea Mon Sep 17 00:00:00 2001 From: Stijn Mathysen Date: Sat, 20 Dec 2008 13:17:50 +0100 Subject: [PATCH] added some comments about the original regex --- activerecord/lib/active_record/validations.rb | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index 9e43cf0..4d6591b 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -821,6 +821,7 @@ module ActiveRecord configuration.update(attr_names.extract_options!) validates_each(attr_names, configuration) do |record, attr_name, value| + # based on the regular expression found on http://www.regular-expressions.info/email.html unless value =~ /\A[\w!#\$%&'*+\/=?^`{|}~-]+(?:\.[\w!#\$%&'*+\/=?^`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[a-z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum)\Z/i record.errors.add(attr_name, :invalid, :default => configuration[:message], :value => value) end -- 1.5.4.5