Class: SEPA::CreditorIdentifierValidator

Inherits:
ActiveModel::Validator
  • Object
show all
Defined in:
lib/sepa_rator/validator.rb

Constant Summary collapse

REGEX =
%r{\A
  [a-zA-Z]{2}                 # ISO country code
  [0-9]{2}                    # Check digits
  [A-Za-z0-9]{3}              # Creditor business code
  [A-Za-z0-9+?/:().,'-]{1,28} # National identifier
\z}x

Instance Method Summary collapse

Instance Method Details

#valid?(creditor_identifier) ⇒ Boolean

Returns:

  • (Boolean)


75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/sepa_rator/validator.rb', line 75

def valid?(creditor_identifier)
  return false unless creditor_identifier.to_s.match?(REGEX)

  # In Germany, the identifier has to be exactly 18 chars long
  return false if creditor_identifier[0..1].match?(/DE/i) && creditor_identifier.length != 18

  # Verify mod-97 check digit (ISO 7064)
  # Structure: CC DD BBB NNNN...
  # CC = country code, DD = check digits, BBB = business code (skipped), N = national id
  # Strip non-alphanumeric chars from national id before check (the spec allows +?/:().,'-
  # but they are ignored for mod-97 computation)
  check_base = creditor_identifier[0..3] + creditor_identifier[7..].gsub(/[^A-Za-z0-9]/, '')
  SEPA.mod97_valid?(check_base[4..] + check_base[0..3])
end

#validate(record) ⇒ Object



66
67
68
69
70
71
72
73
# File 'lib/sepa_rator/validator.rb', line 66

def validate(record)
  field_name = options[:field_name] || :creditor_identifier
  value = record.public_send(field_name)

  return if valid?(value)

  record.errors.add(field_name, :invalid, message: options[:message])
end