Skip to content

Instantly share code, notes, and snippets.

@jcf
Forked from stauntonknight/email_validator.rb
Created September 2, 2011 10:48
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save jcf/1188367 to your computer and use it in GitHub Desktop.
Save jcf/1188367 to your computer and use it in GitHub Desktop.
Rails 3 Email Validator
require 'mail'
class EmailValidator < ActiveModel::EachValidator
attr_reader :record, :attribute, :value, :email, :tree
def validate_each(record, attribute, value)
@record, @attribute, @value = record, attribute, value
@email = Mail::Address.new(value)
@tree = email.__send__(:tree)
add_error unless valid?
rescue Mail::Field::ParseError
add_error
end
private
def valid?
!!(domain_and_address_present? && domain_has_more_than_one_atom?)
end
def domain_and_address_present?
email.domain && email.address == value
end
def domain_has_more_than_one_atom?
tree.domain.dot_atom_text.elements.length > 1
end
def add_error
if message = options[:message]
record.errors[attribute] << message
else
record.errors.add(attribute, :invalid)
end
end
end
require 'spec_helper'
describe Author do
def author(attributes = {})
@author ||= Author.make(attributes) # assuming you're using Machinist
end
describe '#email' do
%w[james@gmail.com man@8.8.8.8 woman@address.tld $@f.c].each do |valid_address|
context "when #{valid_address.inspect}" do
it 'has no errors on email' do
author(email: valid_address).valid?
author.should have(0).errors_on(:email)
end
end
end
%w[haxors @blah can@haz].each do |invalid_address|
context "when #{invalid_address.inspect}" do
it 'has one error on email' do
author(email: invalid_address).valid?
author.should have(1).error_on(:email)
end
end
end
end
end
@benatkin
Copy link

I'm interested in helping you turn this into a gem next time I have free time.

@JamesFerguson
Copy link

I posted this on the original rails-royce blog post as well:

This validator seems to allow multiple email addresses:

p = Person.new
p.name = “Test”
p.email = “test@example.com, test2@example.com
p.valid? # => true

Is that intended?

@JamesFerguson
Copy link

I spoke too soon. I can't see why exactly but your refactored version catches my example where the original didn't.

(My fork of this gist just tests the above case and makes the spec shorter)

@benatkin
Copy link

benatkin commented Nov 4, 2011

@JamesFerguson your example ought to be added to the unit test I think, and this ought to be turned into a gem so the unit tests can be run more easily. (Maybe with a script that builds an example rails/sqlite app.)

@jcf
Copy link
Author

jcf commented Jul 19, 2012

I have packaged this code up in to a gem and shared it on Github.

You can find it at http://github.com/evently/validate_as_email.

@benatkin
Copy link

awesome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment