activemodel-email_address_validator 0.1.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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