missing_validators 1.1.0 → 2.0.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 +4 -4
- data/.travis.yml +1 -0
- data/README.md +7 -11
- data/Rakefile +9 -3
- data/config/locales/en.yml +2 -8
- data/lib/missing_validators.rb +10 -8
- data/lib/missing_validators/matchers/ensure_valid_email_format_of.rb +6 -6
- data/lib/missing_validators/matchers/ensure_valid_imei_format_of.rb +6 -6
- data/lib/missing_validators/matchers/ensure_valid_mac_address_format_of.rb +6 -6
- data/lib/missing_validators/matchers/ensure_valid_url_format_of.rb +6 -6
- data/lib/missing_validators/validators/base_validator.rb +17 -6
- data/lib/missing_validators/validators/color_validator.rb +5 -7
- data/lib/missing_validators/validators/email_validator.rb +20 -10
- data/lib/missing_validators/validators/equality_validator.rb +18 -12
- data/lib/missing_validators/validators/imei_validator.rb +14 -13
- data/lib/missing_validators/validators/inequality_validator.rb +8 -24
- data/lib/missing_validators/validators/latitude_validator.rb +6 -6
- data/lib/missing_validators/validators/longitude_validator.rb +6 -6
- data/lib/missing_validators/validators/mac_address_validator.rb +12 -12
- data/lib/missing_validators/validators/url_validator.rb +37 -19
- data/lib/missing_validators/version.rb +3 -3
- data/missing_validators.gemspec +17 -13
- data/spec/spec_helper.rb +3 -3
- data/spec/validators/color_validator_spec.rb +11 -13
- data/spec/validators/email_validator_spec.rb +31 -21
- data/spec/validators/equality_validator_spec.rb +16 -29
- data/spec/validators/imei_spec.rb +25 -27
- data/spec/validators/inequality_validator_spec.rb +16 -28
- data/spec/validators/latitude_validator_spec.rb +15 -17
- data/spec/validators/longitude_validator_spec.rb +15 -17
- data/spec/validators/mac_address_spec.rb +42 -45
- data/spec/validators/url_validator_spec.rb +44 -44
- metadata +85 -12
- data/lib/missing_validators/matchers/ensure_equality_of_matcher.rb +0 -27
- data/lib/missing_validators/matchers/ensure_inequality_of_matcher.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 606dab4d74f885ca572168fef9a7315ef0c57c30
|
4
|
+
data.tar.gz: c45673eabbc315352ba49d35e59420673be12c25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d48da718a2afb2e6b74c1a12f534b8a3d726873ec889f77c29c0ab30bcb2767295bdabd7f0166b870530949810934fa1eaca256b95d8e3890a35d35e380e2c9
|
7
|
+
data.tar.gz: 8b4880e80d5c3fa9e1ec7aad550d97d87ea6f5db2f494b4a0064cfc5b3bff01742c11114e1e338a7fb9ab13a39863b4f890fcdf5335946fbc9c17cda356817bb
|
data/README.md
CHANGED
@@ -40,9 +40,11 @@ Or any ruby class:
|
|
40
40
|
|
41
41
|
You can specify domains to which the email domain should belong in one of the folowing ways:
|
42
42
|
|
43
|
-
validates :email, email: { domains: 'com' }
|
44
|
-
validates :email, email: { domains:
|
45
|
-
validates :email, email: { domains: [
|
43
|
+
validates :email, email: { domains: '.com' }
|
44
|
+
validates :email, email: { domains: 'example.org' }
|
45
|
+
validates :email, email: { domains: ['.com', '.edu', 'example.org'] }
|
46
|
+
|
47
|
+
Please note that if a domain is specified as a sting starting with "." (for example, ".com") then the valid values should be in the subdomains of this domain (for example, "email@example.com" or "user@subdomain.example.com"). If a domain is specified without leading "." (for example, "example.org"), then the valid values should be in this domain only (for example, "user@example.org" or "email@example.org", but not "email@subdomain.example.org").
|
46
48
|
|
47
49
|
RSpec matcher is also available for your convenience:
|
48
50
|
|
@@ -94,7 +96,7 @@ With an ActiveRecord model:
|
|
94
96
|
|
95
97
|
class Flight < ActiveRecord::Base
|
96
98
|
attr_accessor :origin, :destination
|
97
|
-
validates :origin, inequality: { to:
|
99
|
+
validates :origin, inequality: { to: ->(o) { o.destination } }
|
98
100
|
end
|
99
101
|
|
100
102
|
Or any ruby class:
|
@@ -102,13 +104,7 @@ Or any ruby class:
|
|
102
104
|
class Flight
|
103
105
|
include ActiveModel::Validations
|
104
106
|
attr_accessor :origin, :destination
|
105
|
-
validates :origin, inequality: { to:
|
106
|
-
end
|
107
|
-
|
108
|
-
RSpec matcher is also available for your convenience:
|
109
|
-
|
110
|
-
describe Flight do
|
111
|
-
it { should ensure_inequality_of(:origin).to(:destination) }
|
107
|
+
validates :origin, inequality: { to: ->(o) { o.destination } }
|
112
108
|
end
|
113
109
|
|
114
110
|
### MacAddressValidator
|
data/Rakefile
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
-
require
|
3
|
-
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'cane/rake_task'
|
4
4
|
require 'rspec/core/rake_task'
|
5
5
|
|
6
6
|
RSpec::Core::RakeTask.new('spec')
|
7
7
|
|
8
|
-
task :
|
8
|
+
task default: :spec
|
9
|
+
|
10
|
+
desc 'Run cane to check quality metrics'
|
11
|
+
Cane::RakeTask.new(:quality) do |cane|
|
12
|
+
cane.abc_max = 10
|
13
|
+
cane.no_style = true
|
14
|
+
end
|
data/config/locales/en.yml
CHANGED
@@ -2,8 +2,8 @@ en:
|
|
2
2
|
errors:
|
3
3
|
messages:
|
4
4
|
imei: "is not a valid IMEI"
|
5
|
-
inequality: "cannot be equal to %{
|
6
|
-
equality: "must be equal to %{
|
5
|
+
inequality: "cannot be equal to %{value}"
|
6
|
+
equality: "must be equal to %{value}"
|
7
7
|
email: "is not a valid email address"
|
8
8
|
url: "is not a valid URL"
|
9
9
|
mac_address: "is not a valid MAC address"
|
@@ -12,12 +12,6 @@ en:
|
|
12
12
|
color: "is not a valid hexadecimal color"
|
13
13
|
missing_validators:
|
14
14
|
matchers:
|
15
|
-
ensure_inequality_of:
|
16
|
-
failure_message_for_should: "#{model} should ensure inequality on attribute #{attr}"
|
17
|
-
failure_message_for_should_not: "#{model} should not ensure inequality on attribute #{attr}"
|
18
|
-
ensure_equality_of:
|
19
|
-
failure_message_for_should: "#{model} should ensure equality on attribute #{attr}"
|
20
|
-
failure_message_for_should_not: "#{model} should not ensure equality on attribute #{attr}"
|
21
15
|
ensure_valid_email_format_of:
|
22
16
|
failure_message_for_should: "#{model} should ensure valid email format of attribute #{attr}"
|
23
17
|
failure_message_for_should_not: "#{model} should not ensure valid email format of attribute #{attr}"
|
data/lib/missing_validators.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
require 'active_model'
|
2
|
-
require '
|
2
|
+
require 'addressable/uri'
|
3
3
|
require 'missing_validators/version'
|
4
4
|
require 'missing_validators/validators/base_validator'
|
5
|
-
require 'missing_validators/validators/inequality_validator'
|
6
|
-
require 'missing_validators/matchers/ensure_inequality_of_matcher' if defined?(RSpec)
|
7
5
|
require 'missing_validators/validators/equality_validator'
|
8
|
-
require 'missing_validators/
|
6
|
+
require 'missing_validators/validators/inequality_validator'
|
9
7
|
require 'missing_validators/validators/email_validator'
|
10
|
-
require 'missing_validators/matchers/ensure_valid_email_format_of' if defined?(RSpec)
|
11
8
|
require 'missing_validators/validators/url_validator'
|
12
|
-
require 'missing_validators/matchers/ensure_valid_url_format_of' if defined?(RSpec)
|
13
9
|
require 'missing_validators/validators/mac_address_validator'
|
14
|
-
require 'missing_validators/matchers/ensure_valid_mac_address_format_of' if defined?(RSpec)
|
15
10
|
require 'missing_validators/validators/longitude_validator'
|
16
11
|
require 'missing_validators/validators/latitude_validator'
|
17
12
|
require 'missing_validators/validators/color_validator'
|
18
13
|
require 'missing_validators/validators/imei_validator'
|
19
|
-
|
14
|
+
|
15
|
+
if defined?(RSpec)
|
16
|
+
require 'rspec/matchers'
|
17
|
+
require 'missing_validators/matchers/ensure_valid_email_format_of'
|
18
|
+
require 'missing_validators/matchers/ensure_valid_url_format_of'
|
19
|
+
require 'missing_validators/matchers/ensure_valid_mac_address_format_of'
|
20
|
+
require 'missing_validators/matchers/ensure_valid_imei_format_of'
|
21
|
+
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
RSpec::Matchers.define :ensure_valid_email_format_of do |attribute|
|
2
|
+
root = 'missing_validators.matchers.ensure_valid_email_format_of'
|
3
|
+
|
2
4
|
match do |model|
|
3
|
-
model.send("#{attribute}=",
|
5
|
+
model.send("#{attribute}=", 'invalid@email_address')
|
4
6
|
model.valid?
|
5
7
|
|
6
|
-
if model.errors.
|
8
|
+
if model.errors.to_hash.key?(attribute)
|
7
9
|
model.errors[attribute].include?(I18n.t('errors.messages.email'))
|
8
10
|
end
|
9
11
|
end
|
10
12
|
|
11
13
|
failure_message do |model|
|
12
|
-
I18n.t
|
13
|
-
model: model.class
|
14
|
+
I18n.t("#{root}.failure_message_for_should", model: model.class)
|
14
15
|
end
|
15
16
|
|
16
17
|
failure_message_when_negated do |model|
|
17
|
-
I18n.t
|
18
|
-
model: model.class
|
18
|
+
I18n.t("#{root}.failure_message_for_should_not", model: model.class)
|
19
19
|
end
|
20
20
|
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
RSpec::Matchers.define :ensure_valid_imei_format_of do |attribute|
|
2
|
+
root = 'missing_validators.matchers.ensure_valid_imei_format_of'
|
3
|
+
|
2
4
|
match do |model|
|
3
|
-
model.send("#{attribute}=",
|
5
|
+
model.send("#{attribute}=", 'invalid.imei')
|
4
6
|
model.valid?
|
5
7
|
|
6
|
-
if model.errors.
|
8
|
+
if model.errors.to_hash.key?(attribute)
|
7
9
|
model.errors[attribute].include?(I18n.t('errors.messages.imei'))
|
8
10
|
end
|
9
11
|
end
|
10
12
|
|
11
13
|
failure_message do |model|
|
12
|
-
I18n.t
|
13
|
-
model: model.class
|
14
|
+
I18n.t("#{root}.failure_message_for_should", model: model.class)
|
14
15
|
end
|
15
16
|
|
16
17
|
failure_message_when_negated do |model|
|
17
|
-
I18n.t
|
18
|
-
model: model.class
|
18
|
+
I18n.t("#{root}.failure_message_for_should_not", model: model.class)
|
19
19
|
end
|
20
20
|
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
RSpec::Matchers.define :ensure_valid_mac_address_format_of do |attribute|
|
2
|
+
root = 'missing_validators.matchers.ensure_valid_mac_address_format_of'
|
3
|
+
|
2
4
|
match do |model|
|
3
|
-
model.send("#{attribute}=",
|
5
|
+
model.send("#{attribute}=", 'invalid.mac.address')
|
4
6
|
model.valid?
|
5
7
|
|
6
|
-
if model.errors.
|
8
|
+
if model.errors.to_hash.key?(attribute)
|
7
9
|
model.errors[attribute].include?(I18n.t('errors.messages.mac_address'))
|
8
10
|
end
|
9
11
|
end
|
10
12
|
|
11
13
|
failure_message do |model|
|
12
|
-
I18n.t
|
13
|
-
model: model.class
|
14
|
+
I18n.t("#{root}.failure_message_for_should", model: model.class)
|
14
15
|
end
|
15
16
|
|
16
17
|
failure_message_when_negated do |model|
|
17
|
-
I18n.t
|
18
|
-
model: model.class
|
18
|
+
I18n.t("#{root}.failure_message_for_should_not", model: model.class)
|
19
19
|
end
|
20
20
|
end
|
@@ -1,20 +1,20 @@
|
|
1
1
|
RSpec::Matchers.define :ensure_valid_url_format_of do |attribute|
|
2
|
+
root = 'missing_validators.matchers.ensure_valid_url_format_of'
|
3
|
+
|
2
4
|
match do |model|
|
3
|
-
model.send("#{attribute}=",
|
5
|
+
model.send("#{attribute}=", ' - ')
|
4
6
|
model.valid?
|
5
7
|
|
6
|
-
if model.errors.
|
8
|
+
if model.errors.to_hash.key?(attribute)
|
7
9
|
model.errors[attribute].include?(I18n.t('errors.messages.url'))
|
8
10
|
end
|
9
11
|
end
|
10
12
|
|
11
13
|
failure_message do |model|
|
12
|
-
I18n.t
|
13
|
-
model: model.class
|
14
|
+
I18n.t("#{root}.failure_message_for_should", model: model.class)
|
14
15
|
end
|
15
16
|
|
16
17
|
failure_message_when_negated do |model|
|
17
|
-
I18n.t
|
18
|
-
model: model.class
|
18
|
+
I18n.t("#{root}.failure_message_for_should_not", model: model.class)
|
19
19
|
end
|
20
20
|
end
|
@@ -1,19 +1,30 @@
|
|
1
1
|
# Base class for most validators in the gem.
|
2
2
|
#
|
3
3
|
class BaseValidator < ActiveModel::EachValidator
|
4
|
+
# Checks if an attribute value is valid.
|
5
|
+
#
|
6
|
+
# @param [Object] record object to validate
|
7
|
+
# @param [String] attribute name of the object attribute to validate
|
8
|
+
# @param [Object] value attribute value
|
4
9
|
def validate_each(record, attribute, value)
|
5
|
-
allow_blank = options
|
10
|
+
allow_blank = options.fetch(:allow_blank, false)
|
11
|
+
|
6
12
|
return if allow_blank && value.blank?
|
13
|
+
return if valid?(value, options)
|
7
14
|
|
8
|
-
|
9
|
-
|
10
|
-
record.errors[attribute] << (options[:message] || I18n.t("errors.messages.#{key}"))
|
15
|
+
record.errors[attribute] << options.fetch(:message) do
|
16
|
+
I18n.t(error_message_key)
|
11
17
|
end
|
12
18
|
end
|
13
19
|
|
14
20
|
private
|
15
21
|
|
16
|
-
def
|
17
|
-
|
22
|
+
def valid?(_value, _options)
|
23
|
+
fail NotImplementedError
|
24
|
+
end
|
25
|
+
|
26
|
+
def error_message_key
|
27
|
+
key = self.class.name.underscore.gsub('_validator', '')
|
28
|
+
"errors.messages.#{key}"
|
18
29
|
end
|
19
30
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# Checks if the value of an attribute is a valid hex color.
|
2
2
|
#
|
3
3
|
# @example Validate that the product color is a valid hex color.
|
4
4
|
# class Product << ActiveRecord::Base
|
@@ -6,13 +6,11 @@
|
|
6
6
|
# validates :color, color: true
|
7
7
|
# end
|
8
8
|
class ColorValidator < BaseValidator
|
9
|
-
def self.validate_format(color)
|
10
|
-
!!(color =~ /^#(?:[0-9a-f]{3})(?:[0-9a-f]{3})?$/i)
|
11
|
-
end
|
12
|
-
|
13
9
|
private
|
14
10
|
|
15
|
-
|
16
|
-
|
11
|
+
HEX_COLOR_FORMAT = /^#(?:[0-9a-f]{3})(?:[0-9a-f]{3})?$/i
|
12
|
+
|
13
|
+
def valid?(color, _)
|
14
|
+
(color =~ HEX_COLOR_FORMAT).present?
|
17
15
|
end
|
18
16
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# Checks if the value of an attribute is a valid email address.
|
2
2
|
#
|
3
3
|
# @example Validate that the user email is a valid email address.
|
4
4
|
# class User << ActiveRecord::Base
|
@@ -6,19 +6,29 @@
|
|
6
6
|
# validates :email, email: true
|
7
7
|
# end
|
8
8
|
class EmailValidator < BaseValidator
|
9
|
-
|
10
|
-
|
9
|
+
private
|
10
|
+
|
11
|
+
EMAIL_FORMAT = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
|
12
|
+
|
13
|
+
def valid?(email, options)
|
14
|
+
validate_format(email) && \
|
15
|
+
validate_domain(email, *options[:domain])
|
11
16
|
end
|
12
17
|
|
13
|
-
def
|
14
|
-
|
15
|
-
domains.empty? || domains.any? { |domain| email_downcased.end_with?(".#{domain.downcase}") }
|
18
|
+
def validate_format(email)
|
19
|
+
(email =~ EMAIL_FORMAT).present?
|
16
20
|
end
|
17
21
|
|
18
|
-
|
22
|
+
def validate_domain(email, *domains)
|
23
|
+
return true if domains.blank?
|
24
|
+
|
25
|
+
email_downcased = email.to_s.downcase
|
26
|
+
|
27
|
+
domains.any? do |domain|
|
28
|
+
domain = domain.to_s.downcase
|
29
|
+
domain = "@#{domain}" unless domain.start_with?('.')
|
19
30
|
|
20
|
-
|
21
|
-
|
22
|
-
&& validate_domain(email, [*(options[:domain])])
|
31
|
+
email_downcased.end_with?(domain)
|
32
|
+
end
|
23
33
|
end
|
24
34
|
end
|
@@ -1,24 +1,30 @@
|
|
1
|
-
#
|
2
|
-
# the value of another attribute of an object.
|
1
|
+
# Checks if the value of an attribute is equal to a value or proc result.
|
3
2
|
#
|
4
3
|
class EqualityValidator < ActiveModel::EachValidator
|
5
|
-
# Checks if an attribute value is
|
4
|
+
# Checks if an attribute value is equal to a value or proc result.
|
6
5
|
#
|
7
6
|
# @param [Object] record object to validate
|
8
7
|
# @param [String] attribute name of the object attribute to validate
|
9
8
|
# @param [Object] value attribute value
|
10
9
|
def validate_each(record, attribute, value)
|
11
|
-
|
10
|
+
to = options[:to]
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
record.send(equal_to.to_sym)
|
17
|
-
end
|
12
|
+
reference_value = to.respond_to?(:call) ? options[:to].call(record) : to
|
13
|
+
|
14
|
+
return if compare_value(value, reference_value)
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
record.errors[attribute] << message
|
16
|
+
record.errors[attribute] << options.fetch(:message) do
|
17
|
+
I18n.t(translation_key, value: reference_value)
|
22
18
|
end
|
23
19
|
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def compare_value(value, reference_value)
|
24
|
+
value == reference_value
|
25
|
+
end
|
26
|
+
|
27
|
+
def translation_key
|
28
|
+
'errors.messages.equality'
|
29
|
+
end
|
24
30
|
end
|
@@ -1,18 +1,21 @@
|
|
1
|
-
#
|
1
|
+
# Checks if the value of an attribute is a valid IMEI number.
|
2
2
|
#
|
3
|
-
# @example Validate that
|
3
|
+
# @example Validate that a device IMEI number is valid.
|
4
4
|
# class Device << ActiveRecord::Base
|
5
5
|
# attr_accessor :imei
|
6
6
|
# validates :imei, imei: true
|
7
7
|
# end
|
8
8
|
class ImeiValidator < BaseValidator
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
private
|
10
|
+
|
11
|
+
# 356843052637512 or 35-6843052-637512 or 35.6843052.637512
|
12
|
+
IMEI_FORMAT = /\A[\d\.\:\-\s]+\z/i
|
12
13
|
|
13
|
-
def
|
14
|
-
|
14
|
+
def validate_format(imei_number)
|
15
|
+
(imei_number =~ IMEI_FORMAT).present?
|
16
|
+
end
|
15
17
|
|
18
|
+
def validate_luhn_checksum(numbers)
|
16
19
|
sum, i = 0, 0
|
17
20
|
|
18
21
|
numbers.each_char do |ch|
|
@@ -21,16 +24,14 @@ class ImeiValidator < BaseValidator
|
|
21
24
|
n = 1 + (n - 10) if n >= 10
|
22
25
|
|
23
26
|
sum += n
|
24
|
-
i
|
27
|
+
i += 1
|
25
28
|
end
|
26
29
|
|
27
30
|
(sum % 10).zero?
|
28
31
|
end
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
validate_format(imei.to_s) \
|
34
|
-
&& luhn_valid?(imei.to_s)
|
33
|
+
def valid?(imei, _)
|
34
|
+
validate_format(imei.to_s) && \
|
35
|
+
validate_luhn_checksum(imei.to_s.gsub(/\D/, '').reverse)
|
35
36
|
end
|
36
37
|
end
|