flash_validators 1.1.0 → 3.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/README.md +258 -35
- data/config/locales/en.yml +66 -42
- data/lib/flash_validators/matchers/ensure_valid_alpha_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_alpha_numeric_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_base64_format_of.rb +26 -0
- data/lib/flash_validators/matchers/ensure_valid_boolean_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_credit_card_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_currency_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_cusip_format_of.rb +26 -0
- data/lib/flash_validators/matchers/ensure_valid_email_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_equality_matcher_of.rb +12 -2
- data/lib/flash_validators/matchers/ensure_valid_gtin_format_of.rb +26 -0
- data/lib/flash_validators/matchers/ensure_valid_hex_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_imei_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_ip_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_isbn_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_isin_format_of.rb +26 -0
- data/lib/flash_validators/matchers/ensure_valid_latitude_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_longitude_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_mac_address_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_name_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_password_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_phone_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_sedol_format_of.rb +26 -0
- data/lib/flash_validators/matchers/ensure_valid_slug_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_ssn_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_url_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_username_format_of.rb +10 -2
- data/lib/flash_validators/matchers/ensure_valid_uuid_format_of.rb +26 -0
- data/lib/flash_validators/validators/alpha_numeric_validator.rb +21 -7
- data/lib/flash_validators/validators/alpha_validator.rb +22 -10
- data/lib/flash_validators/validators/base64_validator.rb +9 -0
- data/lib/flash_validators/validators/credit_card_validator.rb +123 -15
- data/lib/flash_validators/validators/currency_validator.rb +13 -7
- data/lib/flash_validators/validators/cusip_validator.rb +33 -0
- data/lib/flash_validators/validators/email_validator.rb +7 -7
- data/lib/flash_validators/validators/equality_validator.rb +7 -7
- data/lib/flash_validators/validators/gtin_validator.rb +59 -0
- data/lib/flash_validators/validators/hex_validator.rb +1 -1
- data/lib/flash_validators/validators/imei_validator.rb +8 -8
- data/lib/flash_validators/validators/isbn_validator.rb +9 -16
- data/lib/flash_validators/validators/isin_validator.rb +38 -0
- data/lib/flash_validators/validators/mac_address_validator.rb +10 -10
- data/lib/flash_validators/validators/password_validator.rb +13 -7
- data/lib/flash_validators/validators/sedol_validator.rb +32 -0
- data/lib/flash_validators/validators/url_validator.rb +13 -13
- data/lib/flash_validators/validators/uuid_validator.rb +28 -0
- data/lib/flash_validators/version.rb +1 -1
- data/lib/flash_validators.rb +12 -0
- data/spec/lib/alpha_numeric_validator_spec.rb +31 -1
- data/spec/lib/alpha_validator_spec.rb +68 -6
- data/spec/lib/base64_validator_spec.rb +33 -0
- data/spec/lib/credit_card_validator_spec.rb +495 -125
- data/spec/lib/cusip_validator_spec.rb +27 -0
- data/spec/lib/gtin_validator_spec.rb +101 -0
- data/spec/lib/hex_validator_spec.rb +20 -0
- data/spec/lib/isin_validator_spec.rb +35 -0
- data/spec/lib/sedol_validator_spec.rb +31 -0
- data/spec/lib/uuid_validator_spec.rb +157 -0
- metadata +26 -2
@@ -1,25 +1,133 @@
|
|
1
1
|
class CreditCardValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
4
|
+
unless valid?(value, options)
|
5
|
+
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.credit_card'))
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
DEFAULT_LENGTHS = {
|
12
|
+
american_express: [15],
|
13
|
+
diners_club: [14, 16],
|
14
|
+
discover: [16],
|
15
|
+
jcb: [16],
|
16
|
+
laser: [16, 17, 18, 19],
|
17
|
+
maestro: [12, 13, 14, 15, 16, 17, 18, 19],
|
18
|
+
mastercard: [16],
|
19
|
+
solo: [16, 18, 19],
|
20
|
+
unionpay: [16, 17, 18, 19],
|
21
|
+
visa: [16]
|
22
|
+
}
|
23
|
+
|
24
|
+
DEFAULT_PREFIXES = {
|
25
|
+
american_express: ['34', '37'],
|
26
|
+
diners_club: ['300', '301', '302', '303', '304', '305', '36', '54', '55'],
|
27
|
+
discover: [
|
28
|
+
'6011', '622126', '622127', '622128', '622129', '62213',
|
29
|
+
'62214', '62215', '62216', '62217', '62218', '62219',
|
30
|
+
'6222', '6223', '6224', '6225', '6226', '6227', '6228',
|
31
|
+
'62290', '62291', '622920', '622921', '622922', '622923',
|
32
|
+
'622924', '622925', '644', '645', '646', '647', '648',
|
33
|
+
'649', '65'
|
34
|
+
],
|
35
|
+
jcb: ['3528', '3529', '353', '354', '355', '356', '357', '358'],
|
36
|
+
laser: ['6304', '6706', '6771', '6709'],
|
37
|
+
maestro: [
|
38
|
+
'5018', '5020', '5038', '6304', '6759', '6761', '6762',
|
39
|
+
'6763', '6764', '6765', '6766'
|
40
|
+
],
|
41
|
+
mastercard: ['51', '52', '53', '54', '55'],
|
42
|
+
solo: ['6334', '6767'],
|
43
|
+
unionpay: [
|
44
|
+
'622126', '622127', '622128', '622129', '62213', '62214',
|
45
|
+
'62215', '62216', '62217', '62218', '62219', '6222', '6223',
|
46
|
+
'6224', '6225', '6226', '6227', '6228', '62290', '62291',
|
47
|
+
'622920', '622921', '622922', '622923', '622924', '622925'
|
48
|
+
],
|
49
|
+
visa: ['4']
|
50
|
+
}
|
51
|
+
|
52
|
+
def valid_format?(value, options)
|
53
|
+
if options[:strict]
|
54
|
+
value =~ /^[0-9]+$/
|
16
55
|
else
|
17
|
-
|
56
|
+
value =~ /^[0-9 -.]+$/
|
18
57
|
end
|
58
|
+
end
|
19
59
|
|
20
|
-
|
21
|
-
|
60
|
+
def valid_length?(value, options)
|
61
|
+
value_size_range = DEFAULT_LENGTHS.values.flatten.uniq.sort
|
62
|
+
value_size = value.size
|
63
|
+
|
64
|
+
case options[:card]
|
65
|
+
when :american_express, :amex
|
66
|
+
DEFAULT_LENGTHS[:american_express].include?(value_size)
|
67
|
+
when :diners_club
|
68
|
+
DEFAULT_LENGTHS[:diners_club].include?(value_size)
|
69
|
+
when :discover
|
70
|
+
DEFAULT_LENGTHS[:discover].include?(value_size)
|
71
|
+
when :jcb
|
72
|
+
DEFAULT_LENGTHS[:jcb].include?(value_size)
|
73
|
+
when :laser
|
74
|
+
DEFAULT_LENGTHS[:laser].include?(value_size)
|
75
|
+
when :maestro
|
76
|
+
DEFAULT_LENGTHS[:maestro].include?(value_size)
|
77
|
+
when :mastercard
|
78
|
+
DEFAULT_LENGTHS[:mastercard].include?(value_size)
|
79
|
+
when :solo
|
80
|
+
DEFAULT_LENGTHS[:solo].include?(value_size)
|
81
|
+
when :unionpay
|
82
|
+
DEFAULT_LENGTHS[:unionpay].include?(value_size)
|
83
|
+
when :visa
|
84
|
+
DEFAULT_LENGTHS[:visa].include?(value_size)
|
85
|
+
else
|
86
|
+
value_size.between?(value_size_range.first, value_size_range.last)
|
22
87
|
end
|
23
88
|
end
|
24
89
|
|
90
|
+
def valid_prefix?(value, options)
|
91
|
+
value_size = value.size
|
92
|
+
|
93
|
+
case options[:card]
|
94
|
+
when :american_express, :amex
|
95
|
+
DEFAULT_PREFIXES[:american_express].any? { |prefix| value.start_with?(prefix) }
|
96
|
+
when :diners_club
|
97
|
+
DEFAULT_PREFIXES[:diners_club].any? { |prefix| value.start_with?(prefix) }
|
98
|
+
when :discover
|
99
|
+
DEFAULT_PREFIXES[:discover].any? { |prefix| value.start_with?(prefix) }
|
100
|
+
when :jcb
|
101
|
+
DEFAULT_PREFIXES[:jcb].any? { |prefix| value.start_with?(prefix) }
|
102
|
+
when :laser
|
103
|
+
DEFAULT_PREFIXES[:laser].any? { |prefix| value.start_with?(prefix) }
|
104
|
+
when :maestro
|
105
|
+
DEFAULT_PREFIXES[:maestro].any? { |prefix| value.start_with?(prefix) }
|
106
|
+
when :mastercard
|
107
|
+
DEFAULT_PREFIXES[:mastercard].any? { |prefix| value.start_with?(prefix) }
|
108
|
+
when :solo
|
109
|
+
DEFAULT_PREFIXES[:solo].any? { |prefix| value.start_with?(prefix) }
|
110
|
+
when :unionpay
|
111
|
+
DEFAULT_PREFIXES[:unionpay].any? { |prefix| value.start_with?(prefix) }
|
112
|
+
when :visa
|
113
|
+
DEFAULT_PREFIXES[:visa].any? { |prefix| value.start_with?(prefix) }
|
114
|
+
else
|
115
|
+
responses = []
|
116
|
+
DEFAULT_LENGTHS.each do |key, values|
|
117
|
+
if values.include?(value_size)
|
118
|
+
responses << DEFAULT_PREFIXES[key].any? { |prefix| value.start_with?(prefix) }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
responses.include?(true)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def valid?(value, options)
|
126
|
+
striped_value = value.to_s.gsub(/\D/, '')
|
127
|
+
|
128
|
+
valid_format?(value, options) &&
|
129
|
+
valid_length?(striped_value, options) &&
|
130
|
+
valid_prefix?(striped_value, options)
|
131
|
+
end
|
132
|
+
|
25
133
|
end
|
@@ -1,17 +1,23 @@
|
|
1
1
|
class CurrencyValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
|
4
|
+
unless valid?(value, options)
|
5
|
+
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.currency'))
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
5
10
|
|
6
|
-
|
7
|
-
|
11
|
+
def valid_format?(value, options)
|
12
|
+
if options[:strict]
|
13
|
+
value =~ /^\d+(\.\d{2})$/
|
8
14
|
else
|
9
|
-
|
15
|
+
value =~ /^\d*+(\.\d{1,2})$/
|
10
16
|
end
|
17
|
+
end
|
11
18
|
|
12
|
-
|
13
|
-
|
14
|
-
end
|
19
|
+
def valid?(value, options)
|
20
|
+
valid_format?(value, options)
|
15
21
|
end
|
16
22
|
|
17
23
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class CusipValidator < ActiveModel::EachValidator
|
2
|
+
|
3
|
+
def validate_each(record, attribute, value)
|
4
|
+
unless valid?(value.to_s)
|
5
|
+
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.cusip'))
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def valid_format?(value)
|
12
|
+
value =~ /^[0-9A-Z]{9}$/
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_checksum?(value)
|
16
|
+
digits = value.split('').map { |i| i.match(/[A-Z]/) ? (i.ord - 55) : i.to_i }
|
17
|
+
even_values = digits.values_at(* digits.each_index.select { |i| i.even? })
|
18
|
+
odd_values = digits.values_at(* digits.each_index.select { |i| i.odd? })
|
19
|
+
values = odd_values.map { |i| i * 2 }.zip(even_values).flatten
|
20
|
+
|
21
|
+
values = values.inject(0) do |sum, i|
|
22
|
+
sum += (i / 10) + i % 10
|
23
|
+
end
|
24
|
+
|
25
|
+
((10 - values) % 10) % 10
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid?(value)
|
29
|
+
valid_format?(value) &&
|
30
|
+
valid_checksum?(value)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -8,18 +8,18 @@ class EmailValidator < ActiveModel::EachValidator
|
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
-
def
|
12
|
-
|
11
|
+
def valid_format?(value)
|
12
|
+
value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
15
|
+
def valid_domain?(value, options)
|
16
|
+
value_downcased = value.downcase
|
17
|
+
options.empty? || options.any? { |domain| value_downcased.end_with?(".#{domain.downcase}") }
|
18
18
|
end
|
19
19
|
|
20
20
|
def valid?(email, options)
|
21
|
-
|
22
|
-
|
21
|
+
valid_format?(email) &&
|
22
|
+
valid_domain?(email, [*(options[:domain])])
|
23
23
|
end
|
24
24
|
|
25
25
|
end
|
@@ -16,12 +16,12 @@ class EqualityValidator < ActiveModel::EachValidator
|
|
16
16
|
private
|
17
17
|
|
18
18
|
OPERATORS = {
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
19
|
+
less_than: :<,
|
20
|
+
less_than_or_equal_to: :<=,
|
21
|
+
greater_than: :>,
|
22
|
+
greater_than_or_equal_to: :>=,
|
23
|
+
equal_to: :==,
|
24
|
+
not_equal_to: :!=
|
25
|
+
}
|
26
26
|
|
27
27
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class GtinValidator < ActiveModel::EachValidator
|
2
|
+
|
3
|
+
def validate_each(record, attribute, value)
|
4
|
+
unless valid?(value, options)
|
5
|
+
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.gtin'))
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def includes_key?(value, options)
|
12
|
+
value.any? { |key| options.keys.include?(key) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_format?(value, options)
|
16
|
+
if options[:strict]
|
17
|
+
value =~ /^[0-9]+$/
|
18
|
+
else
|
19
|
+
value =~ /^[0-9 ]+$/
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid_length?(value, options)
|
24
|
+
value_size = value.size
|
25
|
+
|
26
|
+
case options[:format]
|
27
|
+
when :ean_8, :gtin_8, :ucc_8
|
28
|
+
value_size == 8
|
29
|
+
when :gtin_12, :upc, :upc_a
|
30
|
+
value_size == 12
|
31
|
+
when :ean, :ean_13, :gtin_13, :ucc_13
|
32
|
+
value_size == 13
|
33
|
+
when :gtin_14, :ucc_14
|
34
|
+
value_size == 14
|
35
|
+
else
|
36
|
+
[8, 12, 13, 14].include?(value_size)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def valid_checksum?(value)
|
41
|
+
reversed_values = value.reverse
|
42
|
+
odd = even = 0
|
43
|
+
|
44
|
+
(1..(reversed_values.length - 1)).each do |i|
|
45
|
+
i.even? ? (even += reversed_values[i].chr.to_i) : (odd += reversed_values[i].chr.to_i)
|
46
|
+
end
|
47
|
+
|
48
|
+
reversed_values[0].chr.to_i == (10 - ((odd * 3) + even) % 10)
|
49
|
+
end
|
50
|
+
|
51
|
+
def valid?(value, options)
|
52
|
+
striped_value = value.to_s.gsub(/\D/, '')
|
53
|
+
|
54
|
+
valid_format?(value, options) &&
|
55
|
+
valid_length?(striped_value, options) &&
|
56
|
+
valid_checksum?(striped_value)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class HexValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless value =~ /^#?([
|
4
|
+
unless value =~ /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.hex'))
|
6
6
|
end
|
7
7
|
end
|
@@ -1,19 +1,19 @@
|
|
1
1
|
class ImeiValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless valid?(value.to_s
|
4
|
+
unless valid?(value.to_s)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.imei'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
-
def
|
12
|
-
|
11
|
+
def valid_format?(value)
|
12
|
+
value =~ /\A[\d\.\:\-\s]+\z/i
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
numbers =
|
15
|
+
def valid_luhn?(value)
|
16
|
+
numbers = value.gsub(/\D/, '').reverse
|
17
17
|
|
18
18
|
sum, i = 0, 0
|
19
19
|
|
@@ -29,9 +29,9 @@ class ImeiValidator < ActiveModel::EachValidator
|
|
29
29
|
(sum % 10).zero?
|
30
30
|
end
|
31
31
|
|
32
|
-
def valid?(
|
33
|
-
|
34
|
-
|
32
|
+
def valid?(value)
|
33
|
+
valid_format?(value) &&
|
34
|
+
valid_luhn?(value)
|
35
35
|
end
|
36
36
|
|
37
37
|
end
|
@@ -1,31 +1,24 @@
|
|
1
1
|
class IsbnValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless valid?(value.to_s
|
4
|
+
unless valid?(value.to_s)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.isbn'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
-
def valid_format?(
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
def self.validate_format(isbn)
|
16
|
-
isbn = '' if isbn.nil?
|
17
|
-
isbn.gsub!(/-| /, '')
|
18
|
-
isbn.downcase!
|
11
|
+
def valid_format?(value)
|
12
|
+
value = '' if value.nil?
|
13
|
+
value.gsub!(/-| /, '')
|
14
|
+
value.downcase!
|
19
15
|
|
20
|
-
|
21
|
-
|
22
|
-
else
|
23
|
-
return false
|
24
|
-
end
|
16
|
+
[10, 13].include?(value.size) &&
|
17
|
+
value.chars.all? { |char| ['0','1','2','3','4','5','6','7','8','9','0','x'].include?(char) }
|
25
18
|
end
|
26
19
|
|
27
|
-
def valid?(
|
28
|
-
|
20
|
+
def valid?(value)
|
21
|
+
valid_format?(value)
|
29
22
|
end
|
30
23
|
|
31
24
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class IsinValidator < ActiveModel::EachValidator
|
2
|
+
|
3
|
+
def validate_each(record, attribute, value)
|
4
|
+
unless valid?(value)
|
5
|
+
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.isin'))
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def valid_format?(value)
|
12
|
+
value =~ /^((AF|AX|AL|DZ|AS|AD|AO|AI|AQ|AG|AR|AM|AW|AU|AT|AZ|BS|BH|BD|BB|BY|BE|BZ|BJ|BM|BT|BO|BQ|BA|BW|BV|BR|IO|BN|BG|BF|BI|KH|CM|CA|CV|KY|CF|TD|CL|CN|CX|CC|CO|KM|CG|CD|CK|CR|CI|HR|CU|CW|CY|CZ|DK|DJ|DM|DO|EC|EG|SV|GQ|ER|EE|ET|FK|FO|FJ|FI|FR|GF|PF|TF|GA|GM|GE|DE|GH|GI|GR|GL|GD|GP|GU|GT|GG|GN|GW|GY|HT|HM|VA|HN|HK|HU|IS|IN|ID|IR|IQ|IE|IM|IL|IT|JM|JP|JE|JO|KZ|KE|KI|KP|KR|KW|KG|LA|LV|LB|LS|LR|LY|LI|LT|LU|MO|MK|MG|MW|MY|MV|ML|MT|MH|MQ|MR|MU|YT|MX|FM|MD|MC|MN|ME|MS|MA|MZ|MM|NA|NR|NP|NL|NC|NZ|NI|NE|NG|NU|NF|MP|NO|OM|PK|PW|PS|PA|PG|PY|PE|PH|PN|PL|PT|PR|QA|RE|RO|RU|RW|BL|SH|KN|LC|MF|PM|VC|WS|SM|ST|SA|SN|RS|SC|SL|SG|SX|SK|SI|SB|SO|ZA|GS|SS|ES|LK|SD|SR|SJ|SZ|SE|CH|SY|TW|TJ|TZ|TH|TL|TG|TK|TO|TT|TN|TR|TM|TC|TV|UG|UA|AE|GB|US|UM|UY|UZ|VU|VE|VN|VG|VI|WF|EH|YE|ZM|ZW{2})([A-Z0-9]{9}))(\d{1})$/
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_checksum?(value)
|
16
|
+
digits = value.split('').map { |i| i.match(/[A-Z]/) ? (i.ord - 55) : i.to_i }
|
17
|
+
even_values = digits.values_at(* digits.each_index.select { |i| i.even? })
|
18
|
+
odd_values = digits.values_at(* digits.each_index.select { |i| i.odd? })
|
19
|
+
|
20
|
+
longest, shortest = if even_values.last == value.split('').map(&:to_i)
|
21
|
+
[even_values, odd_values]
|
22
|
+
else
|
23
|
+
[odd_values, even_values]
|
24
|
+
end
|
25
|
+
|
26
|
+
longest = longest.map { |i| i * 2 }
|
27
|
+
values = (longest.concat(shortest)).to_s.scan(/./).map(&:to_i)
|
28
|
+
sum = values.inject(&:+)
|
29
|
+
|
30
|
+
(10 - (sum % 10)) % 10
|
31
|
+
end
|
32
|
+
|
33
|
+
def valid?(value)
|
34
|
+
valid_format?(value) &&
|
35
|
+
valid_checksum?(value)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -1,24 +1,24 @@
|
|
1
1
|
class MacAddressValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless
|
4
|
+
unless valid?(value)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.mac_address'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
def valid_format?(value)
|
12
|
+
(value =~ /^([\h]{2}:){5}[\h]{2}?$/i) ||
|
13
|
+
(value =~ /^([\h]{2}[-|\.|\s]){5}[\h]{2}?$/i) ||
|
14
|
+
(value =~ /^([\h]{6})[-|\.][\h]{6}?$/i) ||
|
15
|
+
(value =~ /^([\h]{6}):[\h]{6}?$/i) ||
|
16
|
+
(value =~ /^([\h]{4}[-|\.|\s]){2}[\h]{4}?$/i) ||
|
17
|
+
(value =~ /^[\h]{12}?$/i)
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
|
20
|
+
def valid?(value)
|
21
|
+
valid_format?(value)
|
22
22
|
end
|
23
23
|
|
24
24
|
end
|
@@ -1,17 +1,23 @@
|
|
1
1
|
class PasswordValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
|
4
|
+
unless valid?(value, options)
|
5
|
+
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.password'))
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
5
10
|
|
6
|
-
|
7
|
-
|
11
|
+
def valid_format?(value, options)
|
12
|
+
if options[:strict]
|
13
|
+
value =~ /^(?=^.{6,18}$)((?=.*[A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z]))^.*$/
|
8
14
|
else
|
9
|
-
|
15
|
+
value =~ /^[a-z0-9!@#$%^&*_-]{6,18}$/
|
10
16
|
end
|
17
|
+
end
|
11
18
|
|
12
|
-
|
13
|
-
|
14
|
-
end
|
19
|
+
def valid?(value, options)
|
20
|
+
valid_format?(value, options)
|
15
21
|
end
|
16
22
|
|
17
23
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class SedolValidator < ActiveModel::EachValidator
|
2
|
+
|
3
|
+
def validate_each(record, attribute, value)
|
4
|
+
unless valid?(value)
|
5
|
+
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.sedol'))
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def valid_format?(value)
|
12
|
+
value =~ /^([A-Z0-9]{6})(\d{1})$/
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_checksum?(value)
|
16
|
+
digits = value.split('').map { |i| i.match(/[A-Z]/) ? (i.ord - 55) : i.to_i }
|
17
|
+
weights = [1, 3, 1, 7, 3, 9, 1]
|
18
|
+
sum = 0
|
19
|
+
|
20
|
+
digits.each_with_index do |i, idx|
|
21
|
+
sum += weights[idx] * i
|
22
|
+
end
|
23
|
+
|
24
|
+
(10 - sum % 10) % 10
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid?(value)
|
28
|
+
valid_format?(value) &&
|
29
|
+
valid_checksum?(value)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -12,25 +12,25 @@ class UrlValidator < ActiveModel::EachValidator
|
|
12
12
|
|
13
13
|
DEFAULT_SCHEMES = [:http, :https]
|
14
14
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
15
|
+
def valid_domain?(value, options)
|
16
|
+
value_downcased = value.host.to_s.downcase
|
17
|
+
options.empty? || options.any? { |domain| value_downcased.end_with?(".#{domain.downcase}") }
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
20
|
+
def valid_scheme?(value, options)
|
21
|
+
value_downcased = value.scheme.to_s.downcase
|
22
|
+
options.empty? || options.any? { |scheme| value_downcased == scheme.to_s.downcase }
|
23
23
|
end
|
24
24
|
|
25
|
-
def
|
26
|
-
['/', ''].include?(
|
25
|
+
def valid_root?(value)
|
26
|
+
['/', ''].include?(value.path) && value.query.blank? && value.fragment.blank?
|
27
27
|
end
|
28
28
|
|
29
|
-
def valid?(
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
def valid?(value, options)
|
30
|
+
value.kind_of?(URI::Generic) &&
|
31
|
+
valid_domain?(value, [*(options[:domain])]) &&
|
32
|
+
valid_scheme?(value, [*(options[:scheme] || UrlValidator::DEFAULT_SCHEMES)]) &&
|
33
|
+
(options[:root] ? valid_root?(value) : true)
|
34
34
|
end
|
35
35
|
|
36
36
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class UuidValidator < ActiveModel::EachValidator
|
2
|
+
|
3
|
+
def validate_each(record, attribute, value)
|
4
|
+
unless valid?(value, options)
|
5
|
+
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.uuid'))
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def valid_format?(value, options)
|
12
|
+
case options[:version]
|
13
|
+
when 3
|
14
|
+
value =~ /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i
|
15
|
+
when 4
|
16
|
+
value =~ /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
|
17
|
+
when 5
|
18
|
+
value =~ /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i
|
19
|
+
else
|
20
|
+
value =~ /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def valid?(value, options)
|
25
|
+
valid_format?(value, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|