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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -1
  3. data/active_validation.gemspec +1 -0
  4. data/config/locales/en.yml +4 -0
  5. data/lib/active_validation/matchers/ensure_valid_alpha_format_of.rb +2 -2
  6. data/lib/active_validation/matchers/ensure_valid_alpha_numeric_format_of.rb +2 -2
  7. data/lib/active_validation/matchers/ensure_valid_base64_format_of.rb +2 -2
  8. data/lib/active_validation/matchers/ensure_valid_boolean_format_of.rb +2 -2
  9. data/lib/active_validation/matchers/ensure_valid_coordinate_format_of.rb +2 -2
  10. data/lib/active_validation/matchers/ensure_valid_credit_card_format_of.rb +2 -2
  11. data/lib/active_validation/matchers/ensure_valid_currency_format_of.rb +2 -2
  12. data/lib/active_validation/matchers/ensure_valid_cusip_format_of.rb +2 -2
  13. data/lib/active_validation/matchers/ensure_valid_email_format_of.rb +2 -2
  14. data/lib/active_validation/matchers/ensure_valid_equality_matcher_of.rb +2 -2
  15. data/lib/active_validation/matchers/ensure_valid_hex_format_of.rb +2 -2
  16. data/lib/active_validation/matchers/ensure_valid_imei_format_of.rb +2 -2
  17. data/lib/active_validation/matchers/ensure_valid_ip_format_of.rb +2 -2
  18. data/lib/active_validation/matchers/ensure_valid_isbn_format_of.rb +2 -2
  19. data/lib/active_validation/matchers/ensure_valid_isin_format_of.rb +2 -2
  20. data/lib/active_validation/matchers/ensure_valid_mac_address_format_of.rb +2 -2
  21. data/lib/active_validation/matchers/ensure_valid_name_format_of.rb +2 -2
  22. data/lib/active_validation/matchers/ensure_valid_password_format_of.rb +2 -2
  23. data/lib/active_validation/matchers/ensure_valid_phone_format_of.rb +2 -2
  24. data/lib/active_validation/matchers/ensure_valid_sedol_format_of.rb +2 -2
  25. data/lib/active_validation/matchers/ensure_valid_slug_format_of.rb +2 -2
  26. data/lib/active_validation/matchers/ensure_valid_ssn_format_of.rb +2 -2
  27. data/lib/active_validation/matchers/ensure_valid_tracking_number_format_of.rb +26 -0
  28. data/lib/active_validation/matchers/ensure_valid_url_format_of.rb +2 -2
  29. data/lib/active_validation/matchers/ensure_valid_username_format_of.rb +2 -2
  30. data/lib/active_validation/matchers/ensure_valid_uuid_format_of.rb +2 -2
  31. data/lib/active_validation/validators/alpha_numeric_validator.rb +10 -7
  32. data/lib/active_validation/validators/alpha_validator.rb +10 -8
  33. data/lib/active_validation/validators/base64_validator.rb +16 -1
  34. data/lib/active_validation/validators/coordinate_validator.rb +12 -3
  35. data/lib/active_validation/validators/credit_card_validator.rb +10 -10
  36. data/lib/active_validation/validators/currency_validator.rb +7 -6
  37. data/lib/active_validation/validators/cusip_validator.rb +11 -9
  38. data/lib/active_validation/validators/email_validator.rb +11 -7
  39. data/lib/active_validation/validators/equality_validator.rb +14 -7
  40. data/lib/active_validation/validators/hex_validator.rb +16 -1
  41. data/lib/active_validation/validators/imei_validator.rb +14 -12
  42. data/lib/active_validation/validators/ip_validator.rb +16 -1
  43. data/lib/active_validation/validators/isbn_validator.rb +8 -4
  44. data/lib/active_validation/validators/isin_validator.rb +16 -14
  45. data/lib/active_validation/validators/mac_address_validator.rb +21 -7
  46. data/lib/active_validation/validators/name_validator.rb +16 -1
  47. data/lib/active_validation/validators/password_validator.rb +7 -6
  48. data/lib/active_validation/validators/phone_validator.rb +16 -1
  49. data/lib/active_validation/validators/sedol_validator.rb +15 -10
  50. data/lib/active_validation/validators/slug_validator.rb +16 -1
  51. data/lib/active_validation/validators/ssn_validator.rb +16 -1
  52. data/lib/active_validation/validators/tracking_number_validator.rb +235 -0
  53. data/lib/active_validation/validators/url_validator.rb +11 -2
  54. data/lib/active_validation/validators/username_validator.rb +16 -1
  55. data/lib/active_validation/validators/uuid_validator.rb +11 -6
  56. data/lib/active_validation/version.rb +1 -1
  57. data/lib/active_validation.rb +5 -6
  58. 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 =~ /^(?:[A-Za-z0-9+$]{4})*(?:[A-Za-z0-9+$]{2}==|[A-Za-z0-9+$]{3}=|[A-Za-z0-9+$]{4})$/
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 value.present? && valid_boundary?(value)
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[:boundary]
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
- if options[:strict]
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
- responses = []
113
+ result = false
116
114
  DEFAULT_LENGTHS.each do |key, values|
117
115
  if values.include?(value_size)
118
- responses << DEFAULT_PREFIXES[key].any? { |prefix| value.start_with?(prefix) }
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
- responses.include?(true)
121
+ return(result)
122
122
  end
123
123
  end
124
124
 
125
125
  def valid?(value, options)
126
- striped_value = value.to_s.gsub(/\D/, '')
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
- if options[:strict]
13
- value =~ /^\d+(\.\d{2})$/
14
- else
15
- value =~ /^\d*+(\.\d{1,2})$/
16
- end
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.split('').map { |i| i.match(/[A-Z]/) ? (i.ord - 55) : i.to_i }
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 valid_domain?(value, options)
16
- value_downcased = value.downcase
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?(email, options)
21
- valid_format?(email) &&
22
- valid_domain?(email, [*(options[:domain])])
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
- to_value = options[:to]
5
- operator = OPERATORS.fetch(options[:operator])
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
- if (options[:operator] == :less_than) || (options[:operator] == :greater_than)
8
- raise Exception if to_value.nil? || operator.nil?
9
- end
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(to_value.to_sym))
12
- record.errors[attribute] << (options[:message] || I18n.t('active_validation.errors.messages.equality', attr: to_value, operator: operator))
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 =~ /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/
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 valid_luhn?(value)
16
- numbers = value.gsub(/\D/, '').reverse
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
- sum += n
26
- i += 1
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
- (sum % 10).zero?
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 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]?)$/
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.nil?
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.chars.all? { |char| ['0','1','2','3','4','5','6','7','8','9','0','x'].include?(char) }
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
- digits = value.split('').map { |i| i.match(/[A-Z]/) ? (i.ord - 55) : i.to_i }
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 = if even_values.last == value.split('').map(&:to_i)
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 = (longest.concat(shortest)).to_s.scan(/./).map(&:to_i)
28
- sum = values.inject(&:+)
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
- (10 - (sum % 10)) % 10
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
- (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)
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 =~ /\A([a-zA-Z'-]+\s+){1,4}[a-zA-Z'-]*\z/i
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
- if options[:strict]
13
- value =~ /^(?=^.{1,255}$)((?=.*[A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z]))^.*$/
14
- else
15
- value =~ /^[a-z0-9!@#$%^&*_-]{1,255}$/
16
- end
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 =~ /^[0-9+\(\)#\.\s\/ext-]+$/i
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.split('').map { |i| i.match(/[A-Z]/) ? (i.ord - 55) : i.to_i }
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
- digits.each_with_index do |i, idx|
21
- sum += weights[idx] * i
15
+ total = 0
16
+ digits.each_with_index do |digit, i|
17
+ total += (weights[i] * digit)
22
18
  end
23
19
 
24
- (10 - sum % 10) % 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 =~ /^[a-z0-9-]+$/
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 =~ /^\A([\d]{3}\-[\d]{2}\-[\d]{4}|[\d]{9})\Z$/
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