active_validation 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +3 -1
- data/active_validation.gemspec +1 -0
- data/config/locales/en.yml +4 -0
- data/lib/active_validation/matchers/ensure_valid_alpha_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_alpha_numeric_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_base64_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_boolean_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_coordinate_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_credit_card_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_currency_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_cusip_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_email_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_equality_matcher_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_hex_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_imei_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_ip_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_isbn_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_isin_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_mac_address_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_name_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_password_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_phone_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_sedol_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_slug_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_ssn_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_tracking_number_format_of.rb +26 -0
- data/lib/active_validation/matchers/ensure_valid_url_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_username_format_of.rb +2 -2
- data/lib/active_validation/matchers/ensure_valid_uuid_format_of.rb +2 -2
- data/lib/active_validation/validators/alpha_numeric_validator.rb +10 -7
- data/lib/active_validation/validators/alpha_validator.rb +10 -8
- data/lib/active_validation/validators/base64_validator.rb +16 -1
- data/lib/active_validation/validators/coordinate_validator.rb +12 -3
- data/lib/active_validation/validators/credit_card_validator.rb +10 -10
- data/lib/active_validation/validators/currency_validator.rb +7 -6
- data/lib/active_validation/validators/cusip_validator.rb +11 -9
- data/lib/active_validation/validators/email_validator.rb +11 -7
- data/lib/active_validation/validators/equality_validator.rb +14 -7
- data/lib/active_validation/validators/hex_validator.rb +16 -1
- data/lib/active_validation/validators/imei_validator.rb +14 -12
- data/lib/active_validation/validators/ip_validator.rb +16 -1
- data/lib/active_validation/validators/isbn_validator.rb +8 -4
- data/lib/active_validation/validators/isin_validator.rb +16 -14
- data/lib/active_validation/validators/mac_address_validator.rb +21 -7
- data/lib/active_validation/validators/name_validator.rb +16 -1
- data/lib/active_validation/validators/password_validator.rb +7 -6
- data/lib/active_validation/validators/phone_validator.rb +16 -1
- data/lib/active_validation/validators/sedol_validator.rb +15 -10
- data/lib/active_validation/validators/slug_validator.rb +16 -1
- data/lib/active_validation/validators/ssn_validator.rb +16 -1
- data/lib/active_validation/validators/tracking_number_validator.rb +235 -0
- data/lib/active_validation/validators/url_validator.rb +11 -2
- data/lib/active_validation/validators/username_validator.rb +16 -1
- data/lib/active_validation/validators/uuid_validator.rb +11 -6
- data/lib/active_validation/version.rb +1 -1
- data/lib/active_validation.rb +5 -6
- metadata +18 -2
@@ -1,9 +1,24 @@
|
|
1
1
|
class Base64Validator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless value
|
4
|
+
unless valid?(value.to_s)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.base64'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
+
private
|
10
|
+
|
11
|
+
def valid_format?(value)
|
12
|
+
value =~ /^(?:[A-Za-z0-9+$]{4})*(?:[A-Za-z0-9+$]{2}==|[A-Za-z0-9+$]{3}=|[A-Za-z0-9+$]{4})$/
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_length?(value)
|
16
|
+
value.present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?(value)
|
20
|
+
valid_length?(value) &&
|
21
|
+
valid_format?(value)
|
22
|
+
end
|
23
|
+
|
9
24
|
end
|
@@ -7,7 +7,7 @@ class CoordinateValidator < ActiveModel::EachValidator
|
|
7
7
|
"Unknown boundary: #{boundary.inspect}. Valid boundaries are: #{BOUNDARIES.map(&:inspect).join(', ')}"
|
8
8
|
end
|
9
9
|
|
10
|
-
unless
|
10
|
+
unless valid?(value, options)
|
11
11
|
record.errors[attribute] << (options[:message] || I18n.t("active_validation.errors.messages.coordinate.#{boundary}"))
|
12
12
|
end
|
13
13
|
end
|
@@ -16,6 +16,10 @@ class CoordinateValidator < ActiveModel::EachValidator
|
|
16
16
|
|
17
17
|
BOUNDARIES = [:coordinate, :latitude, :longitude]
|
18
18
|
|
19
|
+
def valid_length?(value)
|
20
|
+
value.present?
|
21
|
+
end
|
22
|
+
|
19
23
|
def valid_latitude?(value)
|
20
24
|
value >= -90 && value <= 90
|
21
25
|
end
|
@@ -24,8 +28,8 @@ class CoordinateValidator < ActiveModel::EachValidator
|
|
24
28
|
value >= -180 && value <= 180
|
25
29
|
end
|
26
30
|
|
27
|
-
def valid_boundary?(value)
|
28
|
-
case options
|
31
|
+
def valid_boundary?(value, options)
|
32
|
+
case options.fetch(:boundary, :coordinate)
|
29
33
|
when :latitude
|
30
34
|
valid_latitude?(value)
|
31
35
|
when :longitude
|
@@ -35,4 +39,9 @@ class CoordinateValidator < ActiveModel::EachValidator
|
|
35
39
|
end
|
36
40
|
end
|
37
41
|
|
42
|
+
def valid?(value, options)
|
43
|
+
valid_length?(value) &&
|
44
|
+
valid_boundary?(value, options)
|
45
|
+
end
|
46
|
+
|
38
47
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class CreditCardValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless valid?(value, options)
|
4
|
+
unless valid?(value.to_s, options)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.credit_card'))
|
6
6
|
end
|
7
7
|
end
|
@@ -50,14 +50,12 @@ class CreditCardValidator < ActiveModel::EachValidator
|
|
50
50
|
}
|
51
51
|
|
52
52
|
def valid_format?(value, options)
|
53
|
-
|
54
|
-
value =~ /^[0-9]+$/
|
55
|
-
else
|
56
|
-
value =~ /^[0-9 -.]+$/
|
57
|
-
end
|
53
|
+
value =~ (options.fetch(:strict, false) ? /^[0-9]+$/ : /^[0-9 -.]+$/)
|
58
54
|
end
|
59
55
|
|
60
56
|
def valid_length?(value, options)
|
57
|
+
return(false) unless value.present?
|
58
|
+
|
61
59
|
value_size_range = DEFAULT_LENGTHS.values.flatten.uniq.sort
|
62
60
|
value_size = value.size
|
63
61
|
|
@@ -112,18 +110,20 @@ class CreditCardValidator < ActiveModel::EachValidator
|
|
112
110
|
when :visa
|
113
111
|
DEFAULT_PREFIXES[:visa].any? { |prefix| value.start_with?(prefix) }
|
114
112
|
else
|
115
|
-
|
113
|
+
result = false
|
116
114
|
DEFAULT_LENGTHS.each do |key, values|
|
117
115
|
if values.include?(value_size)
|
118
|
-
|
116
|
+
result = DEFAULT_PREFIXES[key].any? { |prefix| value.start_with?(prefix) }
|
117
|
+
break if result
|
119
118
|
end
|
119
|
+
break if result
|
120
120
|
end
|
121
|
-
|
121
|
+
return(result)
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
125
|
def valid?(value, options)
|
126
|
-
striped_value = value.
|
126
|
+
striped_value = value.gsub(/\D/, '')
|
127
127
|
|
128
128
|
valid_format?(value, options) &&
|
129
129
|
valid_length?(striped_value, options) &&
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class CurrencyValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless valid?(value, options)
|
4
|
+
unless valid?(value.to_s, options)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.currency'))
|
6
6
|
end
|
7
7
|
end
|
@@ -9,14 +9,15 @@ class CurrencyValidator < ActiveModel::EachValidator
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def valid_format?(value, options)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
value =~ (options.fetch(:strict, false) ? /^\d+(\.\d{2})$/ : /^\d*+(\.\d{1,2})$/)
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_length?(value)
|
16
|
+
value.present?
|
17
17
|
end
|
18
18
|
|
19
19
|
def valid?(value, options)
|
20
|
+
valid_length?(value) &&
|
20
21
|
valid_format?(value, options)
|
21
22
|
end
|
22
23
|
|
@@ -8,24 +8,26 @@ class CusipValidator < ActiveModel::EachValidator
|
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
-
def valid_format?(value)
|
12
|
-
value =~ /^[0-9A-Z]{9}$/
|
13
|
-
end
|
14
|
-
|
15
11
|
def valid_checksum?(value)
|
16
|
-
digits = value.
|
12
|
+
digits = value.chars.map { |character| character.match(/[A-Z]/) ? (character.ord - 55) : character.to_i }
|
17
13
|
even_values = digits.values_at(* digits.each_index.select { |i| i.even? })
|
18
14
|
odd_values = digits.values_at(* digits.each_index.select { |i| i.odd? })
|
19
15
|
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
|
16
|
+
values = values.inject(0) { |sum, i| sum += (i / 10) + i % 10 }
|
24
17
|
|
25
18
|
((10 - values) % 10) % 10
|
26
19
|
end
|
27
20
|
|
21
|
+
def valid_format?(value)
|
22
|
+
value =~ /^[0-9A-Z]{9}$/
|
23
|
+
end
|
24
|
+
|
25
|
+
def valid_length?(value)
|
26
|
+
value.present?
|
27
|
+
end
|
28
|
+
|
28
29
|
def valid?(value)
|
30
|
+
valid_length?(value) &&
|
29
31
|
valid_format?(value) &&
|
30
32
|
valid_checksum?(value)
|
31
33
|
end
|
@@ -1,25 +1,29 @@
|
|
1
1
|
class EmailValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless valid?(value, options)
|
4
|
+
unless valid?(value.to_s, options)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.email'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
+
def valid_domain?(value, options)
|
12
|
+
options.empty? || options.any? { |domain| value.downcase.end_with?(".#{domain.downcase}") }
|
13
|
+
end
|
14
|
+
|
11
15
|
def valid_format?(value)
|
12
16
|
value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
|
13
17
|
end
|
14
18
|
|
15
|
-
def
|
16
|
-
|
17
|
-
options.empty? || options.any? { |domain| value_downcased.end_with?(".#{domain.downcase}") }
|
19
|
+
def valid_length?(value)
|
20
|
+
value.present?
|
18
21
|
end
|
19
22
|
|
20
|
-
def valid?(
|
21
|
-
|
22
|
-
|
23
|
+
def valid?(value, options)
|
24
|
+
valid_length?(value) &&
|
25
|
+
valid_format?(value) &&
|
26
|
+
valid_domain?(value, [*(options[:domain])])
|
23
27
|
end
|
24
28
|
|
25
29
|
end
|
@@ -1,15 +1,22 @@
|
|
1
1
|
class EqualityValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
|
5
|
-
|
4
|
+
to = options.fetch(:to, nil)
|
5
|
+
if to.nil?
|
6
|
+
raise ArgumentError,
|
7
|
+
"ArgumentError: missing ':to' attribute for comparison."
|
8
|
+
end
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
+
operator = options.fetch(:operator, nil)
|
11
|
+
operators = OPERATORS.keys
|
12
|
+
unless operators.include?(operator)
|
13
|
+
raise ArgumentError,
|
14
|
+
"Unknown operator: #{operator.inspect}. Valid operators are: #{operators.map(&:inspect).join(', ')}"
|
15
|
+
end
|
16
|
+
operator = OPERATORS.fetch(operator)
|
10
17
|
|
11
|
-
unless value.send(operator, record.send(
|
12
|
-
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.equality', attr:
|
18
|
+
unless value.send(operator.to_sym, record.send(to.to_sym))
|
19
|
+
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.equality', attr: to, operator: operator))
|
13
20
|
end
|
14
21
|
end
|
15
22
|
|
@@ -1,9 +1,24 @@
|
|
1
1
|
class HexValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless value
|
4
|
+
unless valid?(value.to_s)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.hex'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
+
private
|
10
|
+
|
11
|
+
def valid_format?(value)
|
12
|
+
value =~ /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_length?(value)
|
16
|
+
value.present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?(value)
|
20
|
+
valid_length?(value) &&
|
21
|
+
valid_format?(value)
|
22
|
+
end
|
23
|
+
|
9
24
|
end
|
@@ -12,24 +12,26 @@ class ImeiValidator < ActiveModel::EachValidator
|
|
12
12
|
value =~ /\A[\d\.\:\-\s]+\z/i
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
sum, i = 0, 0
|
19
|
-
|
20
|
-
numbers.each_char do |ch|
|
21
|
-
n = ch.to_i
|
22
|
-
n *= 2 if i.odd?
|
23
|
-
n = 1 + (n - 10) if n >= 10
|
15
|
+
def valid_length?(value)
|
16
|
+
value.present?
|
17
|
+
end
|
24
18
|
|
25
|
-
|
26
|
-
|
19
|
+
def valid_luhn?(value)
|
20
|
+
number = value.gsub(/\D/, '').reverse
|
21
|
+
|
22
|
+
total = 0
|
23
|
+
number.chars.each_with_index do |character, i|
|
24
|
+
result = character.to_i
|
25
|
+
result *= 2 if i.odd?
|
26
|
+
result = (1 + (result - 10)) if (result >= 10)
|
27
|
+
total += result
|
27
28
|
end
|
28
29
|
|
29
|
-
(
|
30
|
+
(total % 10).zero?
|
30
31
|
end
|
31
32
|
|
32
33
|
def valid?(value)
|
34
|
+
valid_length?(value) &&
|
33
35
|
valid_format?(value) &&
|
34
36
|
valid_luhn?(value)
|
35
37
|
end
|
@@ -1,9 +1,24 @@
|
|
1
1
|
class IpValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless
|
4
|
+
unless valid?(value.to_s)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.ip'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
+
private
|
10
|
+
|
11
|
+
def valid_format?(value)
|
12
|
+
value =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_length?(value)
|
16
|
+
value.present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?(value)
|
20
|
+
valid_length?(value) &&
|
21
|
+
valid_format?(value)
|
22
|
+
end
|
23
|
+
|
9
24
|
end
|
@@ -9,15 +9,19 @@ class IsbnValidator < ActiveModel::EachValidator
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def valid_format?(value)
|
12
|
-
value = '' if value.
|
13
|
-
value.gsub
|
14
|
-
value.downcase!
|
12
|
+
value = '' if value.blank?
|
13
|
+
value = value.gsub(/-| /, '').downcase.chars
|
15
14
|
|
16
15
|
[10, 13].include?(value.size) &&
|
17
|
-
value.
|
16
|
+
value.all? { |character| ['0', '1', '2' , '3', '4', '5', '6', '7', '8', '9', '0', 'x'].include?(character) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid_length?(value)
|
20
|
+
value.present?
|
18
21
|
end
|
19
22
|
|
20
23
|
def valid?(value)
|
24
|
+
valid_length?(value) &&
|
21
25
|
valid_format?(value)
|
22
26
|
end
|
23
27
|
|
@@ -1,36 +1,38 @@
|
|
1
1
|
class IsinValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless valid?(value)
|
4
|
+
unless valid?(value.to_s)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.isin'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
9
|
private
|
10
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
11
|
def valid_checksum?(value)
|
16
|
-
|
12
|
+
characters = value.chars
|
13
|
+
digits = characters.map { |character| character.match(/[A-Z]/) ? (character.ord - 55) : character.to_i }
|
17
14
|
even_values = digits.values_at(* digits.each_index.select { |i| i.even? })
|
18
15
|
odd_values = digits.values_at(* digits.each_index.select { |i| i.odd? })
|
19
16
|
|
20
|
-
longest, shortest =
|
21
|
-
[even_values, odd_values]
|
22
|
-
else
|
23
|
-
[odd_values, even_values]
|
24
|
-
end
|
17
|
+
longest, shortest = (even_values.last == characters.map(&:to_i)) ? [even_values, odd_values] : [odd_values, even_values]
|
25
18
|
|
26
19
|
longest = longest.map { |i| i * 2 }
|
27
|
-
values =
|
28
|
-
|
20
|
+
values = longest.concat(shortest).to_s.scan(/./).map(&:to_i)
|
21
|
+
total = values.inject(&:+)
|
22
|
+
|
23
|
+
(10 - (total % 10)) % 10
|
24
|
+
end
|
25
|
+
|
26
|
+
def valid_format?(value)
|
27
|
+
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})$/
|
28
|
+
end
|
29
29
|
|
30
|
-
|
30
|
+
def valid_length?(value)
|
31
|
+
value.present?
|
31
32
|
end
|
32
33
|
|
33
34
|
def valid?(value)
|
35
|
+
valid_length?(value) &&
|
34
36
|
valid_format?(value) &&
|
35
37
|
valid_checksum?(value)
|
36
38
|
end
|
@@ -1,23 +1,37 @@
|
|
1
1
|
class MacAddressValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless valid?(value)
|
4
|
+
unless valid?(value.to_s)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.mac_address'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
+
DEFAULT_FORMATS = [
|
12
|
+
/^([\h]{2}:){5}[\h]{2}?$/i,
|
13
|
+
/^([\h]{2}[-|\.|\s]){5}[\h]{2}?$/i,
|
14
|
+
/^([\h]{6})[-|\.][\h]{6}?$/i,
|
15
|
+
/^([\h]{6}):[\h]{6}?$/i,
|
16
|
+
/^([\h]{4}[-|\.|\s]){2}[\h]{4}?$/i,
|
17
|
+
/^[\h]{12}?$/i
|
18
|
+
]
|
19
|
+
|
11
20
|
def valid_format?(value)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
(
|
21
|
+
result = false
|
22
|
+
DEFAULT_FORMATS.each do |pattern|
|
23
|
+
result = (value =~ pattern)
|
24
|
+
break if result
|
25
|
+
end
|
26
|
+
return(result)
|
27
|
+
end
|
28
|
+
|
29
|
+
def valid_length?(value)
|
30
|
+
value.present?
|
18
31
|
end
|
19
32
|
|
20
33
|
def valid?(value)
|
34
|
+
valid_length?(value) &&
|
21
35
|
valid_format?(value)
|
22
36
|
end
|
23
37
|
|
@@ -1,9 +1,24 @@
|
|
1
1
|
class NameValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless value
|
4
|
+
unless valid?(value.to_s)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.name'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
+
private
|
10
|
+
|
11
|
+
def valid_format?(value)
|
12
|
+
value =~ /\A([a-zA-Z'-]+\s+){1,4}[a-zA-Z'-]*\z/i
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_length?(value)
|
16
|
+
value.present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?(value)
|
20
|
+
valid_length?(value) &&
|
21
|
+
valid_format?(value)
|
22
|
+
end
|
23
|
+
|
9
24
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class PasswordValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless valid?(value, options)
|
4
|
+
unless valid?(value.to_s, options)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.password'))
|
6
6
|
end
|
7
7
|
end
|
@@ -9,14 +9,15 @@ class PasswordValidator < ActiveModel::EachValidator
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def valid_format?(value, options)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
value =~ (options.fetch(:strict, false) ? /^(?=^.{1,255}$)((?=.*[A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z]))^.*$/ : /^[a-z0-9!@#$%^&*_-]{1,255}$/)
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_length?(value)
|
16
|
+
value.present?
|
17
17
|
end
|
18
18
|
|
19
19
|
def valid?(value, options)
|
20
|
+
valid_length?(value) &&
|
20
21
|
valid_format?(value, options)
|
21
22
|
end
|
22
23
|
|
@@ -1,9 +1,24 @@
|
|
1
1
|
class PhoneValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless value
|
4
|
+
unless valid?(value.to_s)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.phone'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
+
private
|
10
|
+
|
11
|
+
def valid_format?(value)
|
12
|
+
value =~ /^[0-9+\(\)#\.\s\/ext-]+$/i
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_length?(value)
|
16
|
+
value.present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?(value)
|
20
|
+
valid_length?(value) &&
|
21
|
+
valid_format?(value)
|
22
|
+
end
|
23
|
+
|
9
24
|
end
|
@@ -1,30 +1,35 @@
|
|
1
1
|
class SedolValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless valid?(value)
|
4
|
+
unless valid?(value.to_s)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.sedol'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
-
def valid_format?(value)
|
12
|
-
value =~ /^([A-Z0-9]{6})(\d{1})$/
|
13
|
-
end
|
14
|
-
|
15
11
|
def valid_checksum?(value)
|
16
|
-
digits = value.
|
12
|
+
digits = value.chars.map { |digit| digit.match(/[A-Z]/) ? (digit.ord - 55) : digit.to_i }
|
17
13
|
weights = [1, 3, 1, 7, 3, 9, 1]
|
18
|
-
sum = 0
|
19
14
|
|
20
|
-
|
21
|
-
|
15
|
+
total = 0
|
16
|
+
digits.each_with_index do |digit, i|
|
17
|
+
total += (weights[i] * digit)
|
22
18
|
end
|
23
19
|
|
24
|
-
(10 -
|
20
|
+
(10 - total % 10) % 10
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid_format?(value)
|
24
|
+
value =~ /^([A-Z0-9]{6})(\d{1})$/
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid_length?(value)
|
28
|
+
value.present?
|
25
29
|
end
|
26
30
|
|
27
31
|
def valid?(value)
|
32
|
+
valid_length?(value) &&
|
28
33
|
valid_format?(value) &&
|
29
34
|
valid_checksum?(value)
|
30
35
|
end
|
@@ -1,9 +1,24 @@
|
|
1
1
|
class SlugValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless value
|
4
|
+
unless valid?(value.to_s)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.slug'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
+
private
|
10
|
+
|
11
|
+
def valid_format?(value)
|
12
|
+
value =~ /^[a-z0-9_-]+$/
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_length?(value)
|
16
|
+
value.present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?(value)
|
20
|
+
valid_length?(value) &&
|
21
|
+
valid_format?(value)
|
22
|
+
end
|
23
|
+
|
9
24
|
end
|
@@ -1,9 +1,24 @@
|
|
1
1
|
class SsnValidator < ActiveModel::EachValidator
|
2
2
|
|
3
3
|
def validate_each(record, attribute, value)
|
4
|
-
unless value
|
4
|
+
unless valid?(value.to_s)
|
5
5
|
record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.ssn'))
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
+
private
|
10
|
+
|
11
|
+
def valid_format?(value)
|
12
|
+
value =~ /^\A([\d]{3}\-[\d]{2}\-[\d]{4}|[\d]{9})\Z$/
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_length?(value)
|
16
|
+
value.present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def valid?(value)
|
20
|
+
valid_length?(value) &&
|
21
|
+
valid_format?(value)
|
22
|
+
end
|
23
|
+
|
9
24
|
end
|