Class: Ibandit::IBAN

Inherits:
Object
  • Object
show all
Defined in:
lib/ibandit/iban.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(iban) ⇒ IBAN

Returns a new instance of IBAN.



14
15
16
17
# File 'lib/ibandit/iban.rb', line 14

def initialize(iban)
  @iban = iban.to_s.gsub(/\s+/, '').upcase
  @errors = {}
end

Instance Attribute Details

#errors ⇒ Object (readonly)

Returns the value of attribute errors.



6
7
8
# File 'lib/ibandit/iban.rb', line 6

def errors
  @errors
end

#iban ⇒ Object (readonly)

Returns the value of attribute iban.



5
6
7
# File 'lib/ibandit/iban.rb', line 5

def iban
  @iban
end

Class Method Details

.structures ⇒ Object



8
9
10
11
12
# File 'lib/ibandit/iban.rb', line 8

def self.structures
  @structures ||= YAML.load_file(
    File.expand_path('../../../data/structures.yml', __FILE__)
  )
end

Instance Method Details

#account_number ⇒ Object



57
58
59
60
61
62
63
64
# File 'lib/ibandit/iban.rb', line 57

def 
  return '' unless structure

  iban.slice(
    structure[:account_number_position] - 1,
    structure[:account_number_length]
  ) || ''
end

#bank_code ⇒ Object



39
40
41
42
43
44
45
46
# File 'lib/ibandit/iban.rb', line 39

def bank_code
  return '' unless structure

  iban.slice(
    structure[:bank_code_position] - 1,
    structure[:bank_code_length]
  ) || ''
end

#bban ⇒ Object



81
82
83
# File 'lib/ibandit/iban.rb', line 81

def bban
  iban[4..-1] || ''
end

#branch_code ⇒ Object



48
49
50
51
52
53
54
55
# File 'lib/ibandit/iban.rb', line 48

def branch_code
  return '' unless structure && structure[:branch_code_length] > 0

  iban.slice(
    structure[:branch_code_position] - 1,
    structure[:branch_code_length]
  ) || ''
end

#check_digits ⇒ Object



35
36
37
# File 'lib/ibandit/iban.rb', line 35

def check_digits
  iban[2, 2] || ''
end

#country_code ⇒ Object

Component parts #



31
32
33
# File 'lib/ibandit/iban.rb', line 31

def country_code
  iban[0, 2]
end

#iban_national_id ⇒ Object



66
67
68
69
70
71
# File 'lib/ibandit/iban.rb', line 66

def iban_national_id
  return '' unless structure

  national_id = branch_code.nil? ? bank_code : bank_code + branch_code
  national_id.slice(0, structure[:iban_national_id_length])
end

#local_check_digits ⇒ Object



73
74
75
76
77
78
79
# File 'lib/ibandit/iban.rb', line 73

def local_check_digits
  return '' unless structure && structure[:local_check_digit_position]

  iban.slice(structure[:local_check_digit_position] - 1,
             structure[:local_check_digit_length]
  ) || ''
end

#to_s(format = :compact) ⇒ Object



19
20
21
22
23
24
25
# File 'lib/ibandit/iban.rb', line 19

def to_s(format = :compact)
  case format
  when :compact then iban
  when :formatted then formatted
  else raise ArgumentError, "invalid format '#{format}'"
  end
end

#valid? ⇒ Boolean

Validations #

Returns:

  • (Boolean)


89
90
91
92
93
94
95
96
97
# File 'lib/ibandit/iban.rb', line 89

def valid?
  [
    valid_country_code?,
    valid_characters?,
    valid_check_digits?,
    valid_length?,
    valid_format?
  ].all?
end

#valid_characters? ⇒ Boolean

Returns:

  • (Boolean)


136
137
138
139
140
141
142
143
144
# File 'lib/ibandit/iban.rb', line 136

def valid_characters?
  if iban.scan(/[^A-Z0-9]/).any?
    @errors[:characters] = 'Non-alphanumeric characters found: ' \
                           "#{iban.scan(/[^A-Z\d]/).join(' ')}"
    false
  else
    true
  end
end

#valid_check_digits? ⇒ Boolean

Returns:

  • (Boolean)


109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/ibandit/iban.rb', line 109

def valid_check_digits?
  return unless valid_country_code? && valid_characters?

  expected_check_digits = CheckDigit.iban(country_code, bban)
  if check_digits == expected_check_digits
    true
  else
    @errors[:check_digits] = 'Check digits failed modulus check. ' \
                             "Expected '#{expected_check_digits}', " \
                             "received '#{check_digits}'"
    false
  end
end

#valid_country_code? ⇒ Boolean

Returns:

  • (Boolean)


99
100
101
102
103
104
105
106
107
# File 'lib/ibandit/iban.rb', line 99

def valid_country_code?
  if IBAN.structures.key?(country_code)
    true
  else
    @errors[:country_code] = "'#{country_code}' is not a valid " \
                             'ISO 3166-1 IBAN country code'
    false
  end
end

#valid_format? ⇒ Boolean

Returns:

  • (Boolean)


146
147
148
149
150
151
152
153
154
155
# File 'lib/ibandit/iban.rb', line 146

def valid_format?
  return unless valid_country_code?

  if bban =~ Regexp.new(structure[:bban_format])
    true
  else
    @errors[:format] = "Unexpected format for a #{country_code} IBAN."
    false
  end
end

#valid_length? ⇒ Boolean

Returns:

  • (Boolean)


123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/ibandit/iban.rb', line 123

def valid_length?
  return unless valid_country_code?

  if iban.size == structure[:total_length]
    true
  else
    @errors[:length] = "Length doesn't match SWIFT specification " \
                       "(expected #{structure[:total_length]} " \
                       "characters, received #{iban.size})"
    false
  end
end