validator 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +6 -0
- data/README.markdown +17 -5
- data/lib/active_model/validations/email_validator.rb +67 -0
- data/lib/validator/email.rb +38 -0
- data/lib/validator/locale/en.yml +7 -0
- data/lib/validator/version.rb +1 -1
- data/lib/validator.rb +2 -1
- data/spec/domain_validator_spec.rb +2 -2
- data/spec/email_validator_spec.rb +133 -0
- data/spec/test_classes/email.rb +17 -0
- data/validator.gemspec +5 -5
- metadata +13 -22
data/.travis.yml
ADDED
data/README.markdown
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
Active Model Validator
|
1
|
+
Active Model Validator [![Travis](https://secure.travis-ci.org/nahaylo/validator.png)](http://travis-ci.org/nahaylo/validator)
|
2
2
|
============================
|
3
3
|
|
4
|
-
This is a ActiveModel validators for domains and
|
4
|
+
This is a ActiveModel validators for domains, ip addresses and email addresses.
|
5
5
|
|
6
6
|
Installation
|
7
7
|
------------
|
@@ -10,11 +10,12 @@ Installation
|
|
10
10
|
Usage
|
11
11
|
-------
|
12
12
|
|
13
|
-
In your models, the gem provides new validators like :domain or :
|
13
|
+
In your models, the gem provides new validators like :domain, :ip_address or :email
|
14
14
|
|
15
15
|
class Model < ActiveRecord::Base
|
16
16
|
validates :domain_name, :domain => true
|
17
17
|
validates :ip, :ip_address => true
|
18
|
+
validates :email_address, :email => true
|
18
19
|
end
|
19
20
|
|
20
21
|
|
@@ -23,9 +24,9 @@ Domain Validator
|
|
23
24
|
|
24
25
|
validates :domain_name, :domain => true
|
25
26
|
|
26
|
-
validates :domain_name, :domain => {:message => 'custom message'}
|
27
|
+
validates :domain_name, :domain => { :message => 'custom message' }
|
27
28
|
|
28
|
-
# custom full domain
|
29
|
+
# custom full domain and label length
|
29
30
|
validates :domain_name, :domain => { :length => 200, :label_length => 60 }
|
30
31
|
|
31
32
|
|
@@ -47,6 +48,17 @@ Ip Address Validator
|
|
47
48
|
validates :ip, :ip_address => { :message => "custom message" }
|
48
49
|
|
49
50
|
|
51
|
+
Email Address Validator
|
52
|
+
-----------------------
|
53
|
+
|
54
|
+
validates :email_address, :email => true
|
55
|
+
|
56
|
+
validates :email_address, :email => { :message => 'custom message' }
|
57
|
+
|
58
|
+
# custom local part, full domain and label length of email address
|
59
|
+
validates :email_address, :email => { :local_length => 60, :domain => { :length => 200, :label_length => 60 }}
|
60
|
+
|
61
|
+
|
50
62
|
Localization Tricks
|
51
63
|
-------------------
|
52
64
|
To customize error message, you can use { :message => "your custom message" } or simple use Rails localization en.yml file, for instance:
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module Validations
|
3
|
+
class EmailValidator < ActiveModel::EachValidator
|
4
|
+
def initialize(options)
|
5
|
+
options[:local_length] ||= ::Validator::Email::LOCAL_LENGTH
|
6
|
+
|
7
|
+
options[:domain] ||= {}
|
8
|
+
options[:domain_length] = options[:domain][:length] ||= ::Validator::Domain::LENGTH
|
9
|
+
options[:domain_label_length] = options[:domain][:label_length] ||= ::Validator::Domain::LABEL_LENGTH
|
10
|
+
|
11
|
+
super(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate_each(record, attr_name, value)
|
15
|
+
# do not validate if value is empty
|
16
|
+
return if value.nil?
|
17
|
+
|
18
|
+
@validator = ::Validator::Email.new(value)
|
19
|
+
|
20
|
+
unless @validator.is_email?
|
21
|
+
record.errors.add(attr_name, :'email.invalid', options)
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
|
25
|
+
unless @validator.valid_by_local_length?(options[:local_length])
|
26
|
+
record.errors.add(attr_name, :'email.local_length', options)
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
|
30
|
+
unless @validator.valid_by_regexp?
|
31
|
+
record.errors.add(attr_name, :'email.invalid', options)
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
|
35
|
+
# validate domain part of email address
|
36
|
+
@domain_validator = ::Validator::Domain.new(@validator.domain)
|
37
|
+
|
38
|
+
# max domain length
|
39
|
+
unless @domain_validator.valid_by_length?(options[:domain_length])
|
40
|
+
record.errors.add(attr_name, :'email.domain.length', options)
|
41
|
+
end
|
42
|
+
|
43
|
+
# label is limited to between 1 and 63 octets
|
44
|
+
unless @domain_validator.valid_by_label_length?(options[:domain_label_length])
|
45
|
+
record.errors.add(attr_name, :'email.domain.label_length', options)
|
46
|
+
end
|
47
|
+
|
48
|
+
# skip proceeding validation if errors
|
49
|
+
return unless record.errors.blank?
|
50
|
+
|
51
|
+
unless @domain_validator.valid_by_regexp?
|
52
|
+
record.errors.add(attr_name, :'email.domain.invalid', options)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
module HelperMethods
|
58
|
+
# class User < ActiveRecord::Base
|
59
|
+
# validates_email_of :email_address
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
def validates_email_of(*attr_names)
|
63
|
+
validates_with EmailValidator, _merge_attributes(attr_names)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Validator
|
2
|
+
class Email
|
3
|
+
attr_accessor :domain
|
4
|
+
|
5
|
+
# Returns the local part (the left hand side of the @ sign in the email address) of the address
|
6
|
+
# a = Email.new('vitaliy@gmail.com')
|
7
|
+
# a.local #=> 'vitaliy'
|
8
|
+
attr_accessor :local
|
9
|
+
|
10
|
+
LOCAL_LENGTH = 64
|
11
|
+
|
12
|
+
def initialize(value)
|
13
|
+
@value = value
|
14
|
+
self.parse
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse
|
18
|
+
@local, @domain = @value.split(/@/)
|
19
|
+
end
|
20
|
+
|
21
|
+
def is_email?
|
22
|
+
@value.split(/@/).size == 2
|
23
|
+
end
|
24
|
+
|
25
|
+
def valid_by_local_length?(local_length = nil)
|
26
|
+
@local.length <= (local_length || LOCAL_LENGTH)
|
27
|
+
end
|
28
|
+
|
29
|
+
def valid_by_regexp?
|
30
|
+
@value =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
|
31
|
+
end
|
32
|
+
|
33
|
+
# valid if passes all conditions
|
34
|
+
def valid?
|
35
|
+
is_email? and valid_by_local_length? and valid_by_regexp?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/validator/locale/en.yml
CHANGED
@@ -14,3 +14,10 @@ en:
|
|
14
14
|
prefix_invalid:
|
15
15
|
ipv4: "prefix must be in range 1..32"
|
16
16
|
ipv6: "prefix must be in range 1..128"
|
17
|
+
email:
|
18
|
+
invalid: "invalid email address"
|
19
|
+
local_length: "local part of email address is limited to %{local_length} characters"
|
20
|
+
domain:
|
21
|
+
invalid: "invalid domain name"
|
22
|
+
length: "domain name length is limited to %{domain_length} characters"
|
23
|
+
label_length: "domain label length is limited to %{domain_label_length} characters"
|
data/lib/validator/version.rb
CHANGED
data/lib/validator.rb
CHANGED
@@ -4,9 +4,10 @@ require "active_support/inflector"
|
|
4
4
|
|
5
5
|
require "active_model/validations/domain_validator"
|
6
6
|
require "active_model/validations/ip_address_validator"
|
7
|
+
require "active_model/validations/email_validator"
|
7
8
|
|
8
9
|
module Validator
|
9
|
-
%w(domain version ip_address).each do |model|
|
10
|
+
%w(domain version ip_address email).each do |model|
|
10
11
|
autoload model.camelize.to_sym, "validator/#{model}"
|
11
12
|
end
|
12
13
|
end
|
@@ -62,12 +62,12 @@ module ActiveModel
|
|
62
62
|
|
63
63
|
describe 'invalid' do
|
64
64
|
it {
|
65
|
-
domain.domain_name = "
|
65
|
+
domain.domain_name = "not-valid-because-of-length-#{'w'*230}.com"
|
66
66
|
domain.should have_errors_on(:domain_name, 2).with_message(I18n.t(:'errors.messages.domain.length', :length => 255))
|
67
67
|
}
|
68
68
|
|
69
69
|
it {
|
70
|
-
domain.domain_name = "
|
70
|
+
domain.domain_name = "not-valid-because-of-length-of-label#{'w'*230}.com"
|
71
71
|
domain.should have_errors_on(:domain_name, 2).with_message(I18n.t(:'errors.messages.domain.label_length', :label_length => 63))
|
72
72
|
}
|
73
73
|
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'test_classes/email'
|
3
|
+
|
4
|
+
module ActiveModel
|
5
|
+
module Validations
|
6
|
+
describe EmailValidator do
|
7
|
+
let(:email) { TestEmail.new }
|
8
|
+
let(:email_with_domain_length) { TestEmailWithDomainLength.new }
|
9
|
+
let(:email_with_message) { TestEmailWithMessage.new }
|
10
|
+
|
11
|
+
describe "validations" do
|
12
|
+
# for blank email
|
13
|
+
it { email.should be_valid }
|
14
|
+
|
15
|
+
describe 'valid' do
|
16
|
+
|
17
|
+
it {
|
18
|
+
[
|
19
|
+
"a+b@plus-in-local.com",
|
20
|
+
"a_b@underscore-in-local.com",
|
21
|
+
"user@example.com",
|
22
|
+
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@letters-in-local.org",
|
23
|
+
"01234567890@numbers-in-local.net",
|
24
|
+
"a@single-character-in-local.org",
|
25
|
+
"one-character-third-level@a.example.com",
|
26
|
+
"single-character-in-sld@x.org",
|
27
|
+
"local@dash-in-sld.com",
|
28
|
+
"letters-in-sld@123.com",
|
29
|
+
"one-letter-sld@x.org",
|
30
|
+
"uncommon-tld@sld.museum",
|
31
|
+
"uncommon-tld@sld.travel",
|
32
|
+
"uncommon-tld@sld.mobi",
|
33
|
+
"country-code-tld@sld.uk",
|
34
|
+
"country-code-tld@sld.rw",
|
35
|
+
"local@sld.newTLD",
|
36
|
+
"local@sub.domains.com",
|
37
|
+
"aaa@bbb.co.jp",
|
38
|
+
"nigel.worthington@big.co.uk",
|
39
|
+
"f@c.com",
|
40
|
+
"areallylongnameaasdfasdfasdfasdf@asdfasdfasdfasdfasdf.ab.cd.ef.gh.co.ca",
|
41
|
+
"valid@#{'a'*63}.#{'b'*63}.#{'c'*63}.#{'d'*59}.com",
|
42
|
+
"valid@#{'w'*63}.com"
|
43
|
+
].each do |e|
|
44
|
+
email.email = e
|
45
|
+
email.should_not have_errors_on(:email)
|
46
|
+
end
|
47
|
+
}
|
48
|
+
|
49
|
+
it "should be valid with local part length 64" do
|
50
|
+
email.email = "valid_because_of_length#{'w'*41}@valid.domain.com"
|
51
|
+
email.should_not have_errors_on(:email)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should be valid for custom length and label length" do
|
55
|
+
email_with_domain_length.email = "valid@valid-domain.com"
|
56
|
+
email_with_domain_length.should be_valid
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
describe 'invalid' do
|
62
|
+
it "if consists of more then two @" do
|
63
|
+
email.email = 'invali@email@domain.com'
|
64
|
+
email.should have_errors_on(:email).with_message(I18n.t(:'errors.messages.email.invalid'))
|
65
|
+
end
|
66
|
+
|
67
|
+
it {
|
68
|
+
email.email = "invalid_because_of_length#{'w'*41}@valid.domain.com"
|
69
|
+
email.should have_errors_on(:email).with_message(I18n.t(:'errors.messages.email.local_length', :local_length => 64))
|
70
|
+
}
|
71
|
+
|
72
|
+
it {
|
73
|
+
[
|
74
|
+
"f@s",
|
75
|
+
"f@s.c",
|
76
|
+
"@bar.com",
|
77
|
+
"test@example.com@example.com",
|
78
|
+
"test@",
|
79
|
+
"@missing-local.org",
|
80
|
+
"a b@space-in-local.com",
|
81
|
+
"! \#$%\`|@invalid-characters-in-local.org",
|
82
|
+
"<>@[]\`|@even-more-invalid-characters-in-local.org",
|
83
|
+
"missing-sld@.com",
|
84
|
+
"invalid-characters-in-sld@! \"\#$%(),/;<>_[]\`|.org",
|
85
|
+
"missing-dot-before-tld@com",
|
86
|
+
"missing-tld@sld.",
|
87
|
+
"missing-at-sign.net",
|
88
|
+
"unbracketed-IP@127.0.0.1",
|
89
|
+
"invalid-ip@127.0.0.1.26",
|
90
|
+
"another-invalid-ip@127.0.0.256",
|
91
|
+
"IP-and-port@127.0.0.1:25",
|
92
|
+
"the-local-part-is-invalid-if-it-is-longer-than-sixty-four-characters@sld.net",
|
93
|
+
"valid@not-valid-because-of-length-#{'w'*230}.com"
|
94
|
+
].each do |e|
|
95
|
+
email.email = e
|
96
|
+
email.should have_errors_on(:email)#.with_message(I18n.t(:'errors.messages.email.invalid_format'))
|
97
|
+
#puts email.errors.full_messages
|
98
|
+
end
|
99
|
+
}
|
100
|
+
|
101
|
+
it {
|
102
|
+
email.email = "valid-local-part@not-valid-because-of-length-#{'w'*230}.com"
|
103
|
+
email.should have_errors_on(:email).with_message(I18n.t(:'errors.messages.email.domain.length', :domain_length => 255))
|
104
|
+
}
|
105
|
+
|
106
|
+
it {
|
107
|
+
email.email = "valid-local-part@not-valid-because-of-length-of-label#{'w'*230}.com"
|
108
|
+
email.should have_errors_on(:email, 2).with_message(I18n.t(:'errors.messages.email.domain.label_length', :domain_label_length => 63))
|
109
|
+
}
|
110
|
+
|
111
|
+
it {
|
112
|
+
email.email = "valid-local-part@#{'w'*64}.com"
|
113
|
+
email.should have_errors_on(:email).with_message(I18n.t(:'errors.messages.email.domain.label_length', :domain_label_length => 63))
|
114
|
+
}
|
115
|
+
|
116
|
+
context 'custom full domain length and label length' do
|
117
|
+
it {
|
118
|
+
email_with_domain_length.email = "valid-local-part@#{'w'*61}.com"
|
119
|
+
email_with_domain_length.should have_errors_on(:email).with_message(I18n.t(:'errors.messages.email.domain.label_length', :domain_label_length => 60))
|
120
|
+
}
|
121
|
+
|
122
|
+
it {
|
123
|
+
email_with_domain_length.email = "valid-local-part@not-valid-because-of-length-#{'w'*190}.com"
|
124
|
+
email_with_domain_length.should have_errors_on(:email).with_message(I18n.t(:'errors.messages.email.domain.length', :domain_length => 200))
|
125
|
+
}
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class BaseTestEmail
|
2
|
+
include ActiveModel::Validations
|
3
|
+
|
4
|
+
attr_accessor :email
|
5
|
+
end
|
6
|
+
|
7
|
+
class TestEmail < BaseTestEmail
|
8
|
+
validates :email, :email => true
|
9
|
+
end
|
10
|
+
|
11
|
+
class TestEmailWithDomainLength < BaseTestEmail
|
12
|
+
validates :email, :email => { :domain => { :length => 200, :label_length => 60 } }
|
13
|
+
end
|
14
|
+
|
15
|
+
class TestEmailWithMessage < BaseTestEmail
|
16
|
+
validates :email, :email => { :message => 'invalid' }
|
17
|
+
end
|
data/validator.gemspec
CHANGED
@@ -7,9 +7,9 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.version = Validator::VERSION
|
8
8
|
s.authors = ["Vitaliy Nahaylo"]
|
9
9
|
s.email = ["nahaylo@gmail.com"]
|
10
|
-
s.homepage = ""
|
11
|
-
s.summary = "
|
12
|
-
s.description = "
|
10
|
+
s.homepage = "https://github.com/nahaylo/validator"
|
11
|
+
s.summary = "ActiveModel validations for domains, ip addresses and email addresses with fully localization support."
|
12
|
+
s.description = "ActiveModel validations for domains, ip addresses and email addresses with fully localization support."
|
13
13
|
|
14
14
|
s.rubyforge_project = "validator"
|
15
15
|
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
21
|
s.add_dependency "ipaddress"
|
22
|
-
s.add_runtime_dependency 'activemodel',
|
23
|
-
s.add_development_dependency 'activesupport',
|
22
|
+
s.add_runtime_dependency 'activemodel', '>= 3.0.0'
|
23
|
+
s.add_development_dependency 'activesupport', '>= 3.0.0'
|
24
24
|
s.add_development_dependency "rspec"
|
25
25
|
end
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.2
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Vitaliy Nahaylo
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-02-20 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -46,14 +46,6 @@ dependencies:
|
|
46
46
|
- 0
|
47
47
|
- 0
|
48
48
|
version: 3.0.0
|
49
|
-
- - <
|
50
|
-
- !ruby/object:Gem::Version
|
51
|
-
hash: 15
|
52
|
-
segments:
|
53
|
-
- 3
|
54
|
-
- 2
|
55
|
-
- 0
|
56
|
-
version: 3.2.0
|
57
49
|
type: :runtime
|
58
50
|
version_requirements: *id002
|
59
51
|
- !ruby/object:Gem::Dependency
|
@@ -70,14 +62,6 @@ dependencies:
|
|
70
62
|
- 0
|
71
63
|
- 0
|
72
64
|
version: 3.0.0
|
73
|
-
- - <
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
hash: 15
|
76
|
-
segments:
|
77
|
-
- 3
|
78
|
-
- 2
|
79
|
-
- 0
|
80
|
-
version: 3.2.0
|
81
65
|
type: :development
|
82
66
|
version_requirements: *id003
|
83
67
|
- !ruby/object:Gem::Dependency
|
@@ -94,7 +78,7 @@ dependencies:
|
|
94
78
|
version: "0"
|
95
79
|
type: :development
|
96
80
|
version_requirements: *id004
|
97
|
-
description:
|
81
|
+
description: ActiveModel validations for domains, ip addresses and email addresses with fully localization support.
|
98
82
|
email:
|
99
83
|
- nahaylo@gmail.com
|
100
84
|
executables: []
|
@@ -105,25 +89,30 @@ extra_rdoc_files: []
|
|
105
89
|
|
106
90
|
files:
|
107
91
|
- .gitignore
|
92
|
+
- .travis.yml
|
108
93
|
- Gemfile
|
109
94
|
- LICENSE
|
110
95
|
- README.markdown
|
111
96
|
- Rakefile
|
112
97
|
- lib/active_model/validations/domain_validator.rb
|
98
|
+
- lib/active_model/validations/email_validator.rb
|
113
99
|
- lib/active_model/validations/ip_address_validator.rb
|
114
100
|
- lib/validator.rb
|
115
101
|
- lib/validator/domain.rb
|
102
|
+
- lib/validator/email.rb
|
116
103
|
- lib/validator/ip_address.rb
|
117
104
|
- lib/validator/locale/en.yml
|
118
105
|
- lib/validator/version.rb
|
119
106
|
- spec/domain_validator_spec.rb
|
107
|
+
- spec/email_validator_spec.rb
|
120
108
|
- spec/ip_address_validator_spec.rb
|
121
109
|
- spec/spec_helper.rb
|
122
110
|
- spec/test_classes/domain.rb
|
111
|
+
- spec/test_classes/email.rb
|
123
112
|
- spec/test_classes/ip_address.rb
|
124
113
|
- validator.gemspec
|
125
114
|
has_rdoc: true
|
126
|
-
homepage:
|
115
|
+
homepage: https://github.com/nahaylo/validator
|
127
116
|
licenses: []
|
128
117
|
|
129
118
|
post_install_message:
|
@@ -155,10 +144,12 @@ rubyforge_project: validator
|
|
155
144
|
rubygems_version: 1.5.0
|
156
145
|
signing_key:
|
157
146
|
specification_version: 3
|
158
|
-
summary:
|
147
|
+
summary: ActiveModel validations for domains, ip addresses and email addresses with fully localization support.
|
159
148
|
test_files:
|
160
149
|
- spec/domain_validator_spec.rb
|
150
|
+
- spec/email_validator_spec.rb
|
161
151
|
- spec/ip_address_validator_spec.rb
|
162
152
|
- spec/spec_helper.rb
|
163
153
|
- spec/test_classes/domain.rb
|
154
|
+
- spec/test_classes/email.rb
|
164
155
|
- spec/test_classes/ip_address.rb
|