Module: SsnValidation::Ssn

Defined in:
lib/ssn_validation/ssn.rb

Constant Summary collapse

DIGITS =
%w[0 1 2 3 4 5 6 7 8 9].freeze
DIGITS_EX0 =
DIGITS[1..-1]
VALID_ITIN_GROUPS =
[50..65, 70..88, 90..92, 94..99].map(&:to_a).flatten.freeze

Class Method Summary collapse

Class Method Details

.ascending?(ssn) ⇒ Boolean

Returns:

  • (Boolean)


39
40
41
42
43
44
# File 'lib/ssn_validation/ssn.rb', line 39

def self.ascending?(ssn)
  return true if ssn.chars == DIGITS.rotate(ssn[0].to_i)[0..8]
  return true if ssn.chars == DIGITS_EX0.rotate(ssn[0].to_i - 1)

  false
end

.descending?(ssn) ⇒ Boolean

Returns:

  • (Boolean)


46
47
48
49
50
51
# File 'lib/ssn_validation/ssn.rb', line 46

def self.descending?(ssn)
  return true if ssn.chars == DIGITS.reverse.rotate(-(ssn[0].to_i + 1))[0..8]
  return true if ssn.chars == DIGITS_EX0.reverse.rotate(-ssn[0].to_i)

  false
end

.enable_ascending?Boolean

Returns:

  • (Boolean)


64
65
66
# File 'lib/ssn_validation/ssn.rb', line 64

def self.enable_ascending?
  SsnValidation.config.enable_ascending
end

.invalid_itin?(ssn) ⇒ Boolean

Returns:

  • (Boolean)


54
55
56
57
58
# File 'lib/ssn_validation/ssn.rb', line 54

def self.invalid_itin?(ssn)
  return false unless ssn[0] == "9" 
  group = ssn[3..4].to_i
  !VALID_ITIN_GROUPS.include?(group)
end

.test_ssn?(ssn) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/ssn_validation/ssn.rb', line 60

def self.test_ssn?(ssn)
  SsnValidation.config.test_ssns.any? {|p| p.match(ssn)}
end

.validate(ssn) ⇒ Object

returns a hash of 0..n key/value pairs for ssn validation error codes and a default message for each



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/ssn_validation/ssn.rb', line 8

def self.validate(ssn)
  ssn    = ssn.to_s.delete('-') # be lenient with incoming dash chars
  errors = {}
  return errors if test_ssn?(ssn)

  (ssn.length != 9) && errors[:nine_digits]        = "SSN value is not 9 digits"
  (ssn.chars - DIGITS).any? && errors[:non_digits] = "SSN value contains non-digits"
  return errors if errors.any?  # return if basic conditions fail

  (ssn[0..2] == "666") && errors[:excluded_666]       = "SSN value contains excluded area 666-xx-xxxx"
  (ssn.chars - [ssn[0]]).empty? && errors[:repeating] = "SSN value contains repeating digits"
  (ssn[0..2] == "000") && errors[:zero_area]          = "SSN value contains zeros in area number 000-xx-xxxx"
  (ssn[3..4] == "00") && errors[:zero_group]          = "SSN value contains zeros in group number xxx-00-xxxx"
  (ssn[5..8] == "0000") && errors[:zero_serial]       = "SSN value contains zeros in serial number xxx-xx-0000"
  return errors if errors.any?  # return if ssn conditions fail

  # check valid ITIN format last
  invalid_itin?(ssn) && errors[:invalid_itin] = "SSN value contains invalid ITIN format 9xx-[x]x-xxxx"

  # check extra validations for possible fake ssns if enabled
  errors.merge!(validate_ascending_descending(ssn)) if enable_ascending?
  errors
end

.validate_ascending_descending(ssn) ⇒ Object



32
33
34
35
36
37
# File 'lib/ssn_validation/ssn.rb', line 32

def self.validate_ascending_descending(ssn)
  errors = {}
  ascending?(ssn) && errors[:ascending]               = "SSN value contains all ASCENDING digits"
  descending?(ssn) && errors[:descending]             = "SSN value contains all DESCENDING digits"
  return errors 
end