iulianu-iban-tools 0.0.1.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README CHANGED
@@ -1,18 +1,41 @@
1
- Installation
2
- ------------
3
- You will need RubyGems 1.2.0 or later.
1
+ iban-tools is a Ruby library for manipulating and validating
2
+ IBAN account numbers.
4
3
 
5
- gem sources -a http://gems.github.com (you only have to do this once)
6
- sudo gem install iulianu-iban-tools
4
+ Read more about IBAN at:
5
+ http://en.wikipedia.org/wiki/International_Bank_Account_Number
7
6
 
8
- Usage
7
+ USAGE
9
8
  -----
10
9
 
11
- irb(main):001:0> require 'rubygems'
12
- => true
13
- irb(main):002:0> require 'iban-tools'
14
- => true
15
- irb(main):003:0> IBANTools::IBAN.valid? "GB82 WEST 1234 5698 7654 32"
10
+ require 'rubygems'
11
+ require 'iban-tools'
12
+
13
+ IBANTools::IBAN.valid? "GB82 WEST 1234 5698 7654 32"
16
14
  => true
17
15
 
16
+ ### Advanced usage, gives more detailed error messages
17
+
18
+ IBANTools::IBAN.new("XQ75 BADCODE 666").validate
19
+ => [:unknown_country_code, :bad_check_digits]
20
+
21
+ ### Pretty print, canonicalize, and extract fields from an IBAN code
22
+
23
+ iban = IBANTools::IBAN.new " ro49 aaaa 1B31007593840000"
24
+
25
+ iban.code
26
+ => "RO49AAAA1B31007593840000"
27
+
28
+ iban.country_code
29
+ => "RO"
30
+
31
+ iban.prettify
32
+ => "RO49 AAAA 1B31 0075 9384 0000"
33
+
34
+ INSTALLATION
35
+ ------------
36
+ You will need RubyGems 1.2.0 or later.
37
+
38
+ gem sources -a http://gems.github.com
39
+ sudo gem install iulianu-iban-tools
40
+
18
41
 
@@ -3,35 +3,84 @@
3
3
  module IBANTools
4
4
  class IBAN
5
5
 
6
- def self.valid?( code )
7
- new(code).validate.empty?
6
+ def self.valid?( code, rules = nil )
7
+ new(code).validate(rules).empty?
8
8
  end
9
9
 
10
10
  def initialize( code )
11
- @code = code.gsub /\s+/, ''
11
+ @code = IBAN.canonicalize_code(code)
12
12
  end
13
13
 
14
- def validate
14
+ def validate( rules = nil )
15
15
  errors = []
16
16
  return [:too_short] if @code.size < 5
17
- errors << :bad_checksum unless valid_checksum?
17
+ return [:bad_chars] unless @code =~ /^[A-Z0-9]+$/
18
+ errors += validate_against_rules( rules || IBAN.default_rules )
19
+ errors << :bad_check_digits unless valid_check_digits?
18
20
  errors
19
21
  end
20
22
 
21
- def valid_checksum?
23
+ def validate_against_rules( rules )
24
+ errors = []
25
+ return [:unknown_country_code] if rules[country_code].nil?
26
+ errors << :bad_length if rules[country_code]["length"] != @code.size
27
+ errors << :bad_format unless bban =~ rules[country_code]["bban_pattern"]
28
+ errors
29
+ end
30
+
31
+ # The code in canonical form,
32
+ # suitable for storing in a database
33
+ # or sending over the wire
34
+ def code
35
+ @code
36
+ end
37
+
38
+ def country_code
39
+ @code[0..1]
40
+ end
41
+
42
+ def check_digits
43
+ @code[2..3]
44
+ end
45
+
46
+ def bban
47
+ @code[4..-1]
48
+ end
49
+
50
+ def valid_check_digits?
22
51
  numerify.to_i % 97 == 1
23
52
  end
24
53
 
25
54
  def numerify
26
55
  (@code[4..-1] + @code[0..3]).chars.map do |ch|
27
- case ch.upcase
28
- when '0'..'9'
29
- ch
30
- when 'A'..'Z'
31
- (ch[0] - ?A + 10).to_s
32
- end
56
+ case ch
57
+ when '0'..'9'
58
+ ch
59
+ when 'A'..'Z'
60
+ (ch[0] - ?A + 10).to_s
61
+ else
62
+ raise RuntimeError.new("Unexpected char '#{ch}' in IBAN code '#{prettify}'")
63
+ end
33
64
  end.join
34
65
  end
35
66
 
67
+ def to_s
68
+ "#<#{self.class}: #{prettify}>"
69
+ end
70
+
71
+ # The IBAN code in a human-readable format
72
+ def prettify
73
+ @code.gsub(/(.{4})/, '\1 ').strip
74
+ end
75
+
76
+ def self.canonicalize_code( code )
77
+ code.strip.gsub(/\s+/, '').upcase
78
+ end
79
+
80
+ # Load and cache the default rules from rules.yml
81
+ def self.default_rules
82
+ @default_rules = IBANRules.defaults
83
+ end
84
+
36
85
  end
37
86
  end
@@ -0,0 +1,32 @@
1
+ # vim:ts=2:sw=2:et:
2
+
3
+ require 'yaml'
4
+
5
+ module IBANTools
6
+
7
+ class IBANRules
8
+
9
+ def initialize( rules = {} )
10
+ @rules = rules
11
+ end
12
+
13
+ def [](key)
14
+ @rules[key]
15
+ end
16
+
17
+ def self.defaults
18
+ load_from_string( File.read(File.dirname(__FILE__) + "/rules.yml") )
19
+ end
20
+
21
+ def self.load_from_string( string )
22
+ rule_hash = YAML.load(string)
23
+ rule_hash.each do |country_code, specs|
24
+ specs["bban_pattern"] = Regexp.new(specs["bban_pattern"])
25
+ end
26
+ IBANRules.new(rule_hash)
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
@@ -0,0 +1,242 @@
1
+ # Data from http://www.tbg5-finance.org/?ibandocs.shtml/
2
+
3
+ "AD":
4
+ # Andorra
5
+ length: 24
6
+ bban_pattern: "\d{8}[A-Z0-9]{12}"
7
+
8
+ "AL":
9
+ # Albania
10
+ length: 28
11
+ bban_pattern: "\d{8}[A-Z0-9]{16}"
12
+
13
+ "AT":
14
+ # Austria
15
+ length: 20
16
+ bban_pattern: "\d{16}"
17
+
18
+ "BA":
19
+ # Bosnia
20
+ length: 20
21
+ bban_pattern: "\d{16}"
22
+
23
+ "BE":
24
+ # Belgium
25
+ length: 16
26
+ bban_pattern: "\d{12}"
27
+
28
+ "BG":
29
+ # Bulgaria
30
+ length: 22
31
+ bban_pattern: "[A-Z]{4}\d{6}[A-Z0-9]{8}"
32
+
33
+ "CH":
34
+ # Switzerland
35
+ length: 21
36
+ bban_pattern: "\d{5}[A-Z0-9]{12}"
37
+
38
+ "CY":
39
+ # Cyprus
40
+ length: 28
41
+ bban_pattern: "\d{8}[A-Z0-9]{16}"
42
+
43
+ "CZ":
44
+ # Czech Republic
45
+ length: 24
46
+ bban_pattern: "\d{20}"
47
+
48
+ "DE":
49
+ # Germany
50
+ length: 22
51
+ bban_pattern: "\d{18}"
52
+
53
+ "DK":
54
+ # Denmark
55
+ length: 18
56
+ bban_pattern: "\d{14}"
57
+
58
+ "EE":
59
+ # Estonia
60
+ length: 20
61
+ bban_pattern: "\d{16}"
62
+
63
+ "ES":
64
+ # Spain
65
+ length: 24
66
+ bban_pattern: "\d{20}"
67
+
68
+ "FI":
69
+ # Finland
70
+ length: 18
71
+ bban_pattern: "\d{14}"
72
+
73
+ "FO":
74
+ # Faroe Islands
75
+ length: 18
76
+ bban_pattern: "\d{14}"
77
+
78
+ "FR":
79
+ # France
80
+ length: 27
81
+ bban_pattern: "\d{10}[A-Z0-9]{11}\d{2}"
82
+
83
+ "GB":
84
+ # United Kingdom
85
+ length: 22
86
+ bban_pattern: "[A-Z]{4}\d{14}"
87
+
88
+ "GI":
89
+ # Gibraltar
90
+ length: 23
91
+ bban_pattern: "[A-Z]{4}[A-Z0-9]{15}"
92
+
93
+ "GL":
94
+ # Greenland
95
+ length: 18
96
+ bban_pattern: "\d{14}"
97
+
98
+ "GR":
99
+ # Greece
100
+ length: 27
101
+ bban_pattern: "\d{7}[A-Z0-9]{16}"
102
+
103
+ "HR":
104
+ # Croatia
105
+ length: 21
106
+ bban_pattern: "\d{17}"
107
+
108
+ "HU":
109
+ # Hungary
110
+ length: 28
111
+ bban_pattern: "\d{24}"
112
+
113
+ "IE":
114
+ # Ireland
115
+ length: 22
116
+ bban_pattern: "[A-Z]{4}\d{14}"
117
+
118
+ "IL":
119
+ # Israel
120
+ length: 23
121
+ bban_pattern: "\d{19}"
122
+
123
+ "IS":
124
+ # Iceland
125
+ length: 26
126
+ bban_pattern: "\d{22}"
127
+
128
+ "IT":
129
+ # Italy
130
+ length: 27
131
+ bban_pattern: "[A-Z]\d{10}[A-Z0-9]{12}"
132
+
133
+ "LI":
134
+ # Liechtenstein
135
+ length: 21
136
+ bban_pattern: "\d{5}[A-Z0-9]{12}"
137
+
138
+ "LT":
139
+ # Lithuania
140
+ length: 20
141
+ bban_pattern: "\d{16}"
142
+
143
+ "LU":
144
+ # Luxembourg
145
+ length: 20
146
+ bban_pattern: "\d{3}[A-Z0-9]{13}"
147
+
148
+ "LV":
149
+ # Latvia
150
+ length: 21
151
+ bban_pattern: "[A-Z]{4}[A-Z0-9]{13}"
152
+
153
+ "MC":
154
+ # Monaco
155
+ length: 27
156
+ bban_pattern: "\d{10}[A-Z0-9]{11}\d{2}"
157
+
158
+ "ME":
159
+ # Montenegro
160
+ length: 22
161
+ bban_pattern: "\d{18}"
162
+
163
+ "MK":
164
+ # Macedonia
165
+ length: 19
166
+ bban_pattern: "\d{3}[A-Z0-9]{10}\d{2}"
167
+
168
+ "MT":
169
+ # Malta
170
+ length: 31
171
+ bban_pattern: "[A-Z]{4}\d{5}[A-Z0-9]{18}"
172
+
173
+ "MU":
174
+ # Mauritius
175
+ length: 30
176
+ bban_pattern: "[A-Z]{4}\d{19}[A-Z]{3}"
177
+
178
+ "NL":
179
+ # Netherlands
180
+ length: 18
181
+ bban_pattern: "[A-Z]{4}\d{10}"
182
+
183
+ "NO":
184
+ # Norway
185
+ length: 15
186
+ bban_pattern: "\d{11}"
187
+
188
+ "PL":
189
+ # Poland
190
+ length: 28
191
+ bban_pattern: "\d{8}[A-Z0-9]{16}"
192
+
193
+ "PT":
194
+ # Portugal
195
+ length: 25
196
+ bban_pattern: "\d{21}"
197
+
198
+ "RO":
199
+ # Romania
200
+ length: 24
201
+ bban_pattern: "[A-Z]{4}[A-Z0-9]{16}"
202
+
203
+ "RS":
204
+ # Serbia
205
+ length: 22
206
+ bban_pattern: "\d{18}"
207
+
208
+ "SA":
209
+ # Saudi Arabia
210
+ length: 24
211
+ bban_pattern: "\d{2}[A-Z0-9]{18}"
212
+
213
+ "SE":
214
+ # Sweden
215
+ length: 24
216
+ bban_pattern: "\d{20}"
217
+
218
+ "SI":
219
+ # Slovenia
220
+ length: 19
221
+ bban_pattern: "\d{15}"
222
+
223
+ "SK":
224
+ # Slovakia
225
+ length: 24
226
+ bban_pattern: "\d{20}"
227
+
228
+ "SM":
229
+ # San Marino
230
+ length: 27
231
+ bban_pattern: "[A-Z]\d{10}[A-Z0-9]{12}"
232
+
233
+ "TN":
234
+ # Tunisia
235
+ length: 24
236
+ bban_pattern: "\d{20}"
237
+
238
+ "TR":
239
+ # Turkey
240
+ length: 26
241
+ bban_pattern: "\d{5}[A-Z0-9]{17}"
242
+
data/lib/iban-tools.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  # vim:ts=2:sw=2:et:
2
2
 
3
3
  require 'iban-tools/iban.rb'
4
+ require 'iban-tools/iban_rules.rb'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iulianu-iban-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iulian Dogariu
@@ -26,6 +26,8 @@ files:
26
26
  - README
27
27
  - lib/iban-tools.rb
28
28
  - lib/iban-tools/iban.rb
29
+ - lib/iban-tools/iban_rules.rb
30
+ - lib/iban-tools/rules.yml
29
31
  has_rdoc: false
30
32
  homepage:
31
33
  post_install_message: