activemodel-email_address_validator 0.1.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ab1d7fc08cf4665a14bb017c968b338df6561cad
4
- data.tar.gz: 90f10888639066f3c41ae8f8a605766c3a2e8607
2
+ SHA256:
3
+ metadata.gz: b5580fb86ca5fc584177916ac313ca624193f64f06679f441521d5904250d4f2
4
+ data.tar.gz: ea37fa1181553939391da23a0a4894bc4b98186ca8b5f3b3dcb863c041013478
5
5
  SHA512:
6
- metadata.gz: 280ca906a98d1ae8d3fa525811402be9cf40a2e061a109bac5dfc0e023c7017a4324e9d44f746f2d194eb2ecfdd5201f391aec3ff32ade335d5329a479d9ade3
7
- data.tar.gz: e8c5f219aff734af345a3265537492a87f204354ddac415bf7d642c6de930b5c620abf97096ff500a569c766d784ca9a15b4e0cfe14f9f1131b1d556db78fb9e
6
+ metadata.gz: f21ef9f11bf4ed601b420dab39bbe62206c47873226e22ee9c3db0597105aa23ffe8064379cd81f34f9367fbcc742689e5303c417bcb6032eeb7d326e3ff9b35
7
+ data.tar.gz: 4d4e2b281fec06eb2c15a3e5fce997fb67f9c6bb70899bedd5a681c5cc2318a6a89ac68653a239b7735f7a4b18a78bf979f56abcfa1f496a49cc45bc96c37e6a
@@ -0,0 +1,37 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ ruby-version: ['2.4', '2.5', '2.6', '2.7', '3.0', '3.1']
16
+
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.ruby-version }}
23
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
24
+ - name: Run tests
25
+ run: bundle exec rake
26
+
27
+ lint:
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - uses: actions/checkout@v2
31
+ - name: Set up Ruby
32
+ uses: ruby/setup-ruby@v1
33
+ with:
34
+ ruby-version: '3.0'
35
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
36
+ - name: Lint
37
+ run: bundle exec standardrb
data/CHANGELOG.md ADDED
@@ -0,0 +1,64 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
+ and this project adheres to [Semantic Versioning](http://semver.org/).
7
+
8
+ ## Unreleased
9
+
10
+ ### Added
11
+
12
+ -
13
+
14
+ ### Removed
15
+
16
+ -
17
+
18
+
19
+ ## [2.1.0]
20
+
21
+ ### Added
22
+
23
+ - Support for Ruby 3.0. We've also started testing against Ruby 3.1 to be
24
+ prepared.
25
+
26
+ - Email addresses with trailing @'s are no longer accepted. Thanks
27
+ @prognostikos!
28
+
29
+ ## [2.0.0]
30
+
31
+ ### Added
32
+
33
+ - Ability to specify custom rules to use when validating the email address
34
+ using the `:with` option.
35
+
36
+ - Support for Ruby 2.5, 2.5 and 2.6. We've probably always had the support,
37
+ but now we're actually testing it.
38
+
39
+ - Support for ActiveModel 6.
40
+
41
+ ### Removed
42
+
43
+ - Support for Ruby 2.2 and 2.3 that are both EOL. We probably still support
44
+ and work on those versions, but we won't verify and test them any more.
45
+
46
+ ## [1.0.1]
47
+
48
+ ### Added
49
+
50
+ - Reject email addresses with tildes in the hostname
51
+
52
+ ## [1.0.0]
53
+
54
+ ### Added
55
+
56
+ - Support for ActiveModel versions 5 and up
57
+ - A changelog
58
+
59
+ ### Changed
60
+
61
+ - Removed support for Ruby versions older than 2.2.2. ActiveSupport 5.0.0.1
62
+ requires Ruby version >= 2.2.2 so to support ActiveModel 5, which requires
63
+ ActiveSupport 5, we have to say goodbye to Ruby 2.1. If you need to use a
64
+ Ruby version prior to 2.2.2, version 0.1.0 of this gem should still work just fine.
data/Gemfile CHANGED
@@ -3,4 +3,5 @@ source "https://rubygems.org"
3
3
  # Specify your gem's dependencies in activemodel-email_address_validator.gemspec
4
4
  gemspec
5
5
 
6
- gem "coveralls", :require => false
6
+ gem "coveralls", require: false
7
+ gem "standard", require: false
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Email Address Validator
2
2
  ## ActiveModel-style email address format validator
3
3
 
4
- [![Build Status](https://travis-ci.org/substancelab/activemodel-email_address_validator.svg?branch=master)](https://travis-ci.org/substancelab/activemodel-email_address_validator) [![Code Climate](https://codeclimate.com/github/substancelab/activemodel-email_address_validator/badges/gpa.svg)](https://codeclimate.com/github/substancelab/activemodel-email_address_validator) [![Coverage Status](https://coveralls.io/repos/substancelab/activemodel-email_address_validator/badge.svg?branch=more-badges&service=github)](https://coveralls.io/github/substancelab/activemodel-email_address_validator?branch=more-badges) [![Dependency Status](https://gemnasium.com/substancelab/activemodel-email_address_validator.svg)](https://gemnasium.com/substancelab/activemodel-email_address_validator)
4
+ [![Code Climate](https://codeclimate.com/github/substancelab/activemodel-email_address_validator/badges/gpa.svg)](https://codeclimate.com/github/substancelab/activemodel-email_address_validator) [![Coverage Status](https://coveralls.io/repos/substancelab/activemodel-email_address_validator/badge.svg?branch=more-badges&service=github)](https://coveralls.io/github/substancelab/activemodel-email_address_validator?branch=more-badges)
5
5
 
6
6
  Whenever I have wanted to validate an email address it has been because I wanted to be somewhat certain I can send an email to someone. Usually this happens as part of a signup procedure.
7
7
 
@@ -28,6 +28,14 @@ If you want to use a specific regular expression:
28
28
 
29
29
  validates :email, :email_address => {:format => /.+@.+\..+/}
30
30
 
31
+ ### Bring your own logic
32
+
33
+ If a regular expression isn't enough for you, you can include your own rules for email addresses. For example, you could validate that all email adresses belong to the same company:
34
+
35
+ validates :email, :email_address => {
36
+ :with => proc { |address| address.end_with?("@substancelab.com") }
37
+ }
38
+
31
39
  ### Verify domain (still to be done - pull request, anybody?)
32
40
 
33
41
  This also checks that the domain actually has an MX record. Note this might take a while because of DNS lookups.
@@ -64,6 +72,7 @@ Or install it yourself as:
64
72
  * https://github.com/codyrobbins/active-model-email-validator
65
73
  * https://github.com/franckverrot/activevalidators
66
74
  * https://github.com/hallelujah/valid_email
75
+ * https://github.com/micke/valid_email2
67
76
  * https://github.com/validates-email-format-of/validates_email_format_of
68
77
 
69
78
  ### Clientside
data/Rakefile CHANGED
@@ -6,7 +6,7 @@ Rake::TestTask.new(:test) do |t|
6
6
  t.libs << "test"
7
7
  end
8
8
 
9
- task :default => :test
9
+ task default: :test
10
10
 
11
11
  desc "Launch an IRB console with the gem loaded"
12
12
  task :console do
@@ -1,25 +1,24 @@
1
- # coding: utf-8
2
1
  lib = File.expand_path("../lib", __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require "activemodel_email_address_validator/version"
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "activemodel-email_address_validator"
8
- spec.version = ActiveModelEmailAddressValidator::VERSION
9
- spec.authors = ["Jakob Skjerning"]
10
- spec.email = ["jakob@mentalized.net"]
11
- spec.summary = "ActiveModel-style email address format validator"
12
- spec.homepage = ""
13
- spec.license = "MIT"
6
+ spec.name = "activemodel-email_address_validator"
7
+ spec.version = ActiveModelEmailAddressValidator::VERSION
8
+ spec.authors = ["Jakob Skjerning"]
9
+ spec.email = ["jakob@mentalized.net"]
10
+ spec.summary = "ActiveModel-style email address format validator"
11
+ spec.homepage = ""
12
+ spec.license = "MIT"
14
13
 
15
- spec.files = `git ls-files -z`.split("\x0")
16
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
17
  spec.require_paths = ["lib"]
19
18
 
20
- spec.add_dependency "activemodel", "~> 4.0"
19
+ spec.add_dependency "activemodel", ">= 4.0", "< 7.0"
21
20
 
22
- spec.add_development_dependency "bundler", "~> 1.7"
23
- spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_development_dependency "bundler", ">= 1.7"
22
+ spec.add_development_dependency "rake", ">= 10.0"
24
23
  spec.add_development_dependency "minitest"
25
24
  end
@@ -25,14 +25,14 @@ module ActiveModelEmailAddressValidator
25
25
  end
26
26
 
27
27
  def valid_using_default?
28
- return false if address =~ /\s+/
29
- email_parts = address.split("@")
28
+ return false if /\s+/.match?(address)
29
+ email_parts = address.split("@", -1)
30
30
 
31
31
  return false unless email_parts.size == 2
32
32
 
33
33
  user, host = *email_parts
34
- return false unless user =~ /^([^.]+\S)*[^. ]+$/
35
- return false unless host =~ /^([^,. ]+\.)+[^,. ]+$/
34
+ return false unless /^([^.]+\S)*[^. ]+$/.match?(user)
35
+ return false unless /^([^,. ~]+\.)+[^,. ]+$/.match?(host)
36
36
  true
37
37
  end
38
38
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveModelEmailAddressValidator
2
- VERSION = "0.1.0"
2
+ VERSION = "2.1.0"
3
3
  end
@@ -3,13 +3,45 @@ require "activemodel_email_address_validator/email_address"
3
3
 
4
4
  class EmailAddressValidator < ActiveModel::EachValidator
5
5
  def validate_each(record, attribute, value)
6
- address = ActiveModelEmailAddressValidator::EmailAddress.new(value)
7
- regex = options[:format]
8
- invalidate(record, attribute) unless address.valid?(regex)
6
+ rules = Array(options[:with] || [])
7
+ if rules.empty?
8
+ # We are using the old syntax, assume regular expressions
9
+ rules = [build_rule_from_format(options[:format])]
10
+ end
11
+
12
+ invalidate(record, attribute) unless all_rules_pass?(rules, value)
9
13
  end
10
14
 
11
15
  private
12
16
 
17
+ def all_rules_pass?(rules, address)
18
+ evaluators = rules.map { |rule| build_evaluator(rule) }
19
+ results = evaluators.map { |evaluator| evaluator.call(address) }
20
+ results.all?
21
+ end
22
+
23
+ # Returns an evaluator for the given rule. Evaluators are objects that respond
24
+ # to `#call` with an arity of 1; the raw attribute value in question.
25
+ #
26
+ # The return-value of `#call` should be `true` if the address passes the given
27
+ # rule, false otherwise.
28
+ def build_evaluator(rule)
29
+ case rule
30
+ when Regexp
31
+ proc { |a| a =~ rule }
32
+ else
33
+ rule
34
+ end
35
+ end
36
+
37
+ def build_rule_from_format(format)
38
+ proc { |attribute_value|
39
+ address =
40
+ ActiveModelEmailAddressValidator::EmailAddress.new(attribute_value)
41
+ address.valid?(format)
42
+ }
43
+ end
44
+
13
45
  def invalidate(record, attribute)
14
46
  record.errors.add(attribute, :invalid)
15
47
  end
@@ -5,6 +5,10 @@ class EmailAddressValidTest < MiniTest::Test
5
5
  accept("bob@example.com")
6
6
  end
7
7
 
8
+ def test_accepts_non_us_ascii_in_local_part
9
+ accept("bøb@example.com")
10
+ end
11
+
8
12
  def test_rejects_email_address_without_at_sign
9
13
  reject("bobexample.com")
10
14
  end
@@ -97,10 +101,22 @@ class EmailAddressValidTest < MiniTest::Test
97
101
  reject("my@nice@domain.com")
98
102
  end
99
103
 
104
+ def test_rejects_leading_at_signs
105
+ reject("@my@domain.com")
106
+ end
107
+
108
+ def test_rejects_trailing_at_signs
109
+ reject("my@domain.com@")
110
+ end
111
+
100
112
  def test_rejects_commas_in_hostname
101
113
  reject("my@domain.com,")
102
114
  end
103
115
 
116
+ def test_rejects_tildes_in_hostname
117
+ reject("my@~domain.com")
118
+ end
119
+
104
120
  def test_handles_long_failing_strings
105
121
  reject("fernandeztorralbofrancisco@sabadellatlantico.")
106
122
  end
@@ -6,3 +6,21 @@ require "activemodel-email_address_validator"
6
6
 
7
7
  require "minitest/autorun"
8
8
  require "minitest/spec"
9
+
10
+ SIMPLEST_VALIDATION = {email: {email_address: true}}
11
+
12
+ def build_model_with_validations(validations = SIMPLEST_VALIDATION)
13
+ klass = Class.new do
14
+ include ActiveModel::Validations
15
+ def self.model_name
16
+ ActiveModel::Name.new(self, nil, "ValidatorModel")
17
+ end
18
+
19
+ validations.each do |attribute, options|
20
+ attr_accessor attribute
21
+ validates attribute, options
22
+ end
23
+ end
24
+ klass.new
25
+ end
26
+ # rubocop:enable Metrics/MethodLength
@@ -1,24 +1,6 @@
1
1
  require "minitest_helper"
2
2
  require "active_model"
3
3
 
4
- # rubocop:disable Metrics/MethodLength
5
- SIMPLEST_VALIDATION = {:email => {:email_address => true}}
6
- def build_model_with_validations(validations = SIMPLEST_VALIDATION)
7
- klass = Class.new do
8
- include ActiveModel::Validations
9
- def self.model_name
10
- ActiveModel::Name.new(self, nil, "ValidatorModel")
11
- end
12
-
13
- validations.each do |attribute, options|
14
- attr_accessor attribute
15
- validates attribute, options
16
- end
17
- end
18
- klass.new
19
- end
20
- # rubocop:enable Metrics/MethodLength
21
-
22
4
  class EmailAddressValidatorTest < MiniTest::Test
23
5
  def setup
24
6
  @subject = build_model_with_validations
@@ -26,22 +8,22 @@ class EmailAddressValidatorTest < MiniTest::Test
26
8
 
27
9
  def test_accepts_nil_email_address
28
10
  @subject = build_model_with_validations(
29
- :email => {:email_address => true, :allow_nil => true}
11
+ email: {email_address: true, allow_nil: true}
30
12
  )
31
- accept(nil)
13
+ accept(nil, @subject)
32
14
  end
33
15
 
34
16
  def test_accepts_valid_email_address
35
- accept("bob@example.com")
17
+ accept("bob@example.com", @subject)
36
18
  end
37
19
 
38
20
  def test_rejects_invalid_email_address
39
- reject("bobexample.com")
21
+ reject("bobexample.com", @subject)
40
22
  end
41
23
 
42
24
  def test_adds_errors_to_validated_attribute
43
25
  subject = build_model_with_validations(
44
- :work_email => {:email_address => true}
26
+ work_email: {email_address: true}
45
27
  )
46
28
  subject.work_email = "whatever"
47
29
  subject.valid?
@@ -51,23 +33,52 @@ class EmailAddressValidatorTest < MiniTest::Test
51
33
 
52
34
  def test_validates_with_custom_regular_expression
53
35
  subject = build_model_with_validations(
54
- :email => {:email_address => {:format => /.+@enterprise\..+/}}
36
+ email: {email_address: {format: /.+@enterprise\..+/}}
37
+ )
38
+ accept("whatever@enterprise.museum", subject)
39
+ reject("totally@valid.com", subject)
40
+ end
41
+
42
+ def test_validates_with_custom_regular_as_a_rule
43
+ subject = build_model_with_validations(
44
+ email: {email_address: {with: /.+@enterprise\..+/}}
45
+ )
46
+ accept("whatever@enterprise.museum", subject)
47
+ reject("totally@valid.com", subject)
48
+ end
49
+
50
+ def test_validates_with_proc
51
+ subject = build_model_with_validations(
52
+ email: {email_address: {
53
+ with: proc { |address| address == "foo" }
54
+ }}
55
+ )
56
+ accept("foo", subject)
57
+ reject("foo@bar.com", subject)
58
+ end
59
+
60
+ def test_validates_with_multiple_procs
61
+ subject = build_model_with_validations(
62
+ email: {email_address: {
63
+ with: [
64
+ proc { |address| address == "ada" },
65
+ proc { |address| address.reverse == address }
66
+ ]
67
+ }}
55
68
  )
56
- subject.email = "whatever@enterprise.museum"
57
- assert subject.valid?
58
- subject.email = "totally@valid.com"
59
- assert !subject.valid?
69
+ accept("ada", subject)
70
+ reject("bob", subject)
60
71
  end
61
72
 
62
73
  private
63
74
 
64
- def accept(email_address)
65
- @subject.email = email_address
66
- assert @subject.valid?, "Expected #{email_address.inspect} to be valid"
75
+ def accept(email_address, subject)
76
+ subject.email = email_address
77
+ assert subject.valid?, "Expected #{email_address.inspect} to be valid"
67
78
  end
68
79
 
69
- def reject(email_address)
70
- @subject.email = email_address
71
- assert !@subject.valid?, "Expected #{email_address.inspect} to be invalid"
80
+ def reject(email_address, subject)
81
+ subject.email = email_address
82
+ assert !subject.valid?, "Expected #{email_address.inspect} to be invalid"
72
83
  end
73
84
  end
metadata CHANGED
@@ -1,55 +1,61 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemodel-email_address_validator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakob Skjerning
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-26 00:00:00.000000000 Z
11
+ date: 2021-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '4.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7.0'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '4.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7.0'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: bundler
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
- - - "~>"
37
+ - - ">="
32
38
  - !ruby/object:Gem::Version
33
39
  version: '1.7'
34
40
  type: :development
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
- - - "~>"
44
+ - - ">="
39
45
  - !ruby/object:Gem::Version
40
46
  version: '1.7'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: rake
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
- - - "~>"
51
+ - - ">="
46
52
  - !ruby/object:Gem::Version
47
53
  version: '10.0'
48
54
  type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
51
57
  requirements:
52
- - - "~>"
58
+ - - ">="
53
59
  - !ruby/object:Gem::Version
54
60
  version: '10.0'
55
61
  - !ruby/object:Gem::Dependency
@@ -66,15 +72,16 @@ dependencies:
66
72
  - - ">="
67
73
  - !ruby/object:Gem::Version
68
74
  version: '0'
69
- description:
75
+ description:
70
76
  email:
71
77
  - jakob@mentalized.net
72
78
  executables: []
73
79
  extensions: []
74
80
  extra_rdoc_files: []
75
81
  files:
82
+ - ".github/workflows/ruby.yml"
76
83
  - ".gitignore"
77
- - ".travis.yml"
84
+ - CHANGELOG.md
78
85
  - Gemfile
79
86
  - LICENSE.txt
80
87
  - README.md
@@ -91,7 +98,7 @@ homepage: ''
91
98
  licenses:
92
99
  - MIT
93
100
  metadata: {}
94
- post_install_message:
101
+ post_install_message:
95
102
  rdoc_options: []
96
103
  require_paths:
97
104
  - lib
@@ -106,9 +113,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
113
  - !ruby/object:Gem::Version
107
114
  version: '0'
108
115
  requirements: []
109
- rubyforge_project:
110
- rubygems_version: 2.4.6
111
- signing_key:
116
+ rubygems_version: 3.2.32
117
+ signing_key:
112
118
  specification_version: 4
113
119
  summary: ActiveModel-style email address format validator
114
120
  test_files:
data/.travis.yml DELETED
@@ -1,13 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.0.0
4
- - 2.1.7
5
- - 2.2.0
6
- - 2.2.1
7
- - 2.2.2
8
- - 2.2.3
9
- - jruby-9.0.0.0
10
-
11
- notifications:
12
- recipients:
13
- - jakob@mentalized.net