-
-
Save jcf/1188367 to your computer and use it in GitHub Desktop.
| 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[[email protected] [email protected] [email protected] [email protected]].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 |
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 = “[email protected], [email protected]”
p.valid? # => true
Is that intended?
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)
@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.)
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.
awesome!
I'm interested in helping you turn this into a gem next time I have free time.