elfproef 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Guardfile ADDED
@@ -0,0 +1,19 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+ # Capybara request specs
17
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
18
+ end
19
+
data/README.md CHANGED
@@ -2,12 +2,10 @@
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/sytzeloor/elfproef.png?branch=master)](http://travis-ci.org/sytzeloor/elfproef)
4
4
 
5
- This gem adds a validation method for Dutch bank account numbers and
6
- Citizen Service Numbers (BSN). These can be validated using the
7
- so-called Elfproef.
5
+ This gem adds two validators to your arsenal:
8
6
 
9
- Based on:
10
- [Elfproef](https://github.com/tilsammans/elfproef/) by tilsammans
7
+ * BsnValidator will validate Burgerservicenummers (Dutch social security numbers). It accepts both 8 and 9 digit BSN numbers.
8
+ * BankAccountValidator will validate ING accounts (1-7 digits), and 9 or 10 digit bank account numbers using the elven-test.
11
9
 
12
10
  ## Installation
13
11
 
@@ -25,16 +23,25 @@ and run
25
23
 
26
24
  ## Usage
27
25
 
28
- Simply add "validates_elfproef_of" to your model class.
26
+ Using the BsnValidator
29
27
 
30
- class User < ActiveRecord::Base
31
- # Validate with 11-test, do not allow 7 digit ING account numbers
32
- validates :bsn, elfproef: true
28
+ class User < ActiveRecord::Base
29
+ validates :bsn_number, bsn: true
30
+ end
33
31
 
34
- # Validate bank account numbers with 11-test, allow 7 digit ING account numbers
35
- validates :bank_account, elfproef: { allow_ing: true }
32
+ Using the BankAccountValidator
33
+
34
+ class User < ActiveRecord::Base
35
+ validates :account_number, bank_account: true
36
36
  end
37
37
 
38
+ You can also use these validators without `ActiveRecord` by including `ActiveModel::Validations`.
39
+
40
+ class AwesomeDutchPerson
41
+ include ActiveModel::Validations
42
+ validates :bsn, bsn: true
43
+ end
44
+
38
45
  ## Bugs / Feature Requests
39
46
 
40
47
  Please post them to
data/elfproef.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
- require "version"
3
+ require "elfproef/version"
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "elfproef"
data/lib/elfproef.rb CHANGED
@@ -1,30 +1,3 @@
1
- require "active_model"
2
- require "active_model/validations"
3
-
4
- # define my validator
5
- class ElfproefValidator < ActiveModel::EachValidator
6
- # implement the method where the validation logic must reside
7
- def validate_each(record, attribute, value)
8
- record.errors.add(attribute, options[:message] || "is not valid") unless Elfproef.elfproef(value, options)
9
- end
10
- end
11
-
12
-
13
- # Elfproef.
14
- module Elfproef
15
- # Calculates the elfproef of a Dutch bank account number or Citizen Service Number (BSN).
16
- # Return value should be 0 (proof succeeded). Any other value means faillure.
17
- # Postbank bank accounts (7 digits) cannot be validated using the elfproef and
18
- # will always return 0 (success).
19
- # http://nl.wikipedia.org/wiki/Elfproef
20
- def self.elfproef(number, options = {})
21
- number, sum = number.to_s, 0
22
- number.gsub!(/\D/, '') # strip out any non-digit character.
23
- return true if options[:allow_ing] && (1..7).include?(number.length) # always pass ING accounts (between 1 and 7 digits)
24
- return false unless (9..10).include?(number.length) # account should be exactly 9 or 10 digits
25
- (1..number.length).each do |c|
26
- sum += number[-c].chr.to_i * c
27
- end
28
- sum % 11 == 0
29
- end
30
- end
1
+ require 'elfproef/version'
2
+ require 'elfproef/bsn_validator'
3
+ require 'elfproef/bank_account_validator'
@@ -0,0 +1,56 @@
1
+ require "active_model"
2
+ require "active_model/validations"
3
+
4
+ # Validates if the specified value is a valid
5
+ # bank account number using the 11-test
6
+ class BankAccountValidator < ActiveModel::EachValidator
7
+ def validate_each(record, attribute, value)
8
+ record.errors.add(attribute, options[:message] || "is not valid") unless validate_account_number(value, options)
9
+ end
10
+
11
+ private
12
+
13
+ # Takes the bank account number and returns true if:
14
+ #
15
+ # * The number is 1...7 digit ING account number (no verification is possible)
16
+ # * Is 9 or 10 digits and passes the 11-test
17
+ #
18
+ def validate_account_number(value, options = {})
19
+ number = value.to_s.gsub(/\D/, '').strip
20
+
21
+ # Not valid if length is 0, 8 or > 10
22
+ return false if number.length == 0 || number.length == 8 || number.length > 10
23
+
24
+ # ING account numbers
25
+ return true if (1..7).include?(number.length)
26
+
27
+ # Validate length 9 and 10 numbers as bank accounts
28
+ validate_with_eleven_test(number)
29
+ end
30
+
31
+ # Performs the actual 11-test on a
32
+ # 9 or 10 digit account number
33
+ #
34
+ # For 10 digits (prefix with a 0 for 9 digits):
35
+ #
36
+ # 0123456789
37
+ # ABCDEFGHIJ
38
+ #
39
+ # sum = 1*A + 2*B + 3*C + 4*D + 5*E + 6*F + 7*G + 8*H + 9*I + 10*J
40
+ #
41
+ # If sum % 11 is 0, the number is valid, otherwise
42
+ # a typo has been made or the number is outright invalid.
43
+ def validate_with_eleven_test(number)
44
+ # Make sure we have a 10 digit account number,
45
+ # Prefix with a 0 if necessary
46
+ number = "0#{number}" if number.length == 9
47
+
48
+ # Calculate the sum
49
+ sum = 0
50
+ number.split("").each_with_index do |char, i|
51
+ sum += char.to_i * (i+1)
52
+ end
53
+
54
+ sum % 11 == 0
55
+ end
56
+ end
@@ -0,0 +1,41 @@
1
+ require "active_model"
2
+ require "active_model/validations"
3
+
4
+ # Validates if the specified value is a valid
5
+ # Burgerservicenummer (Dutch social security number)
6
+ class BsnValidator < ActiveModel::EachValidator
7
+ def validate_each(record, attribute, value)
8
+ record.errors.add(attribute, options[:message] || "is not valid") unless validate_bsn(value, options)
9
+ end
10
+
11
+ private
12
+
13
+ # A BSN is an 8 or 9 digit Dutch social security
14
+ # number.
15
+ def validate_bsn(value, options = {})
16
+ bsn = value.to_s.gsub(/\D/, '').strip
17
+
18
+ # Only allow 8 or 9 digits
19
+ return false if bsn.length < 8 || bsn.length > 9
20
+
21
+ # Validate with the advanced eleven test
22
+ validate_with_advanced_eleven_test(bsn)
23
+ end
24
+
25
+ def validate_with_advanced_eleven_test(number)
26
+ # Make sure we have 9 digits
27
+ number = "0#{number}" if number.size == 8
28
+
29
+ numbers = number.split("").map(&:to_i)
30
+ control, numbers = numbers.pop, numbers.reverse
31
+
32
+
33
+ sum = 0
34
+ numbers.each_with_index do |digit, i|
35
+ sum += digit * (i+2)
36
+ end
37
+
38
+ sum.remainder(11) == control
39
+ end
40
+ end
41
+
@@ -1,3 +1,3 @@
1
1
  module Elfproef
2
- VERSION= "0.0.3"
2
+ VERSION= "0.1.0"
3
3
  end
@@ -0,0 +1,76 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe BankAccountValidator do
4
+ subject {
5
+ Class.new do
6
+ include ActiveModel::Validations
7
+ attr_accessor :account
8
+ validates :account, :bank_account => true
9
+ end.new
10
+ }
11
+
12
+ let(:errors) { ["is not valid"] }
13
+
14
+ it "accepts 1 digit ING accounts" do
15
+ subject.account = "1"
16
+ subject.should be_valid
17
+ end
18
+
19
+ it "accepts 2 digit ING accounts" do
20
+ subject.account = "12"
21
+ subject.should be_valid
22
+ end
23
+
24
+ it "accepts 3 digit ING accounts" do
25
+ subject.account = "3"
26
+ subject.should be_valid
27
+ end
28
+
29
+ it "accepts 4 digit ING accounts" do
30
+ subject.account = "4"
31
+ subject.should be_valid
32
+ end
33
+
34
+ it "accepts 5 digit ING accounts" do
35
+ subject.account = "5"
36
+ subject.should be_valid
37
+ end
38
+
39
+ it "accepts 6 digit ING accounts" do
40
+ subject.account = "6"
41
+ subject.should be_valid
42
+ end
43
+
44
+ it "accepts 7 digit ING accounts" do
45
+ subject.account = "7"
46
+ subject.should be_valid
47
+ end
48
+
49
+ it "accepts a valid 9 digit bank account number" do
50
+ subject.account = "123456789"
51
+ subject.should be_valid
52
+ end
53
+
54
+ it "accepts a valid 10 digit bank account number" do
55
+ subject.account = "0123456789"
56
+ subject.should be_valid
57
+ end
58
+
59
+ it "fails on an 8 digit number" do
60
+ subject.account = "12345678"
61
+ subject.should_not be_valid
62
+ subject.errors[:account].should == errors
63
+ end
64
+
65
+ it "fails on obviously wrong numbers" do
66
+ subject.account = "CHUCKNORRIS"
67
+ subject.should_not be_valid
68
+ subject.errors[:account].should == errors
69
+ end
70
+
71
+ it "fails on 1 digit errors" do
72
+ subject.account = "133456789"
73
+ subject.should_not be_valid
74
+ subject.errors[:account].should == errors
75
+ end
76
+ end
@@ -0,0 +1,47 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe BsnValidator do
4
+ subject {
5
+ Class.new do
6
+ include ActiveModel::Validations
7
+ attr_accessor :number
8
+ validates :number, :bsn => true
9
+ end.new
10
+ }
11
+
12
+ let(:errors) { ["is not valid"] }
13
+
14
+ it "accepts an 8 digit bsn" do
15
+ subject.number = "12345672"
16
+ subject.should be_valid
17
+ end
18
+
19
+ it "accepts a 9 digit bsn" do
20
+ subject.number = "123456782"
21
+ subject.should be_valid
22
+ end
23
+
24
+ it "rejects too short bsn numbers" do
25
+ subject.number = "123"
26
+ subject.should_not be_valid
27
+ subject.errors[:number].should == errors
28
+ end
29
+
30
+ it "rejects too long bsn numbers" do
31
+ subject.number = "123456789012345"
32
+ subject.should_not be_valid
33
+ subject.errors[:number].should == errors
34
+ end
35
+
36
+ it "rejects obvious incorrect bsn numbers" do
37
+ subject.number = "NOTAXES"
38
+ subject.should_not be_valid
39
+ subject.errors[:number].should == errors
40
+ end
41
+
42
+ it "rejects mistyped bsn numbers" do
43
+ subject.number = "123456789012345"
44
+ subject.should_not be_valid
45
+ subject.errors[:number].should == errors
46
+ end
47
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elfproef
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-03-13 00:00:00.000000000 Z
13
+ date: 2012-03-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
17
- requirement: &70105363295440 !ruby/object:Gem::Requirement
17
+ requirement: &70122195961320 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: *70105363295440
25
+ version_requirements: *70122195961320
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: rspec
28
- requirement: &70105363294960 !ruby/object:Gem::Requirement
28
+ requirement: &70122195960660 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *70105363294960
36
+ version_requirements: *70122195960660
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: guard-rspec
39
- requirement: &70105363294520 !ruby/object:Gem::Requirement
39
+ requirement: &70122195959980 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *70105363294520
47
+ version_requirements: *70122195959980
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: activemodel
50
- requirement: &70105363293980 !ruby/object:Gem::Requirement
50
+ requirement: &70122195959000 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,7 +55,7 @@ dependencies:
55
55
  version: '0'
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *70105363293980
58
+ version_requirements: *70122195959000
59
59
  description: Validation for Dutch bank account numbers and Citizen Service Numbers
60
60
  (BSN)
61
61
  email:
@@ -68,12 +68,16 @@ files:
68
68
  - .gitignore
69
69
  - .travis.yml
70
70
  - Gemfile
71
+ - Guardfile
71
72
  - README.md
72
73
  - Rakefile
73
74
  - elfproef.gemspec
74
75
  - lib/elfproef.rb
75
- - lib/version.rb
76
- - spec/elfproef_spec.rb
76
+ - lib/elfproef/bank_account_validator.rb
77
+ - lib/elfproef/bsn_validator.rb
78
+ - lib/elfproef/version.rb
79
+ - spec/bank_account_validator_spec.rb
80
+ - spec/bsn_validator_spec.rb
77
81
  - spec/spec_helper.rb
78
82
  homepage: https://github.com/sytzeloor/elfproef
79
83
  licenses: []
@@ -87,18 +91,25 @@ required_ruby_version: !ruby/object:Gem::Requirement
87
91
  - - ! '>='
88
92
  - !ruby/object:Gem::Version
89
93
  version: '0'
94
+ segments:
95
+ - 0
96
+ hash: -1515901023488646711
90
97
  required_rubygems_version: !ruby/object:Gem::Requirement
91
98
  none: false
92
99
  requirements:
93
100
  - - ! '>='
94
101
  - !ruby/object:Gem::Version
95
102
  version: '0'
103
+ segments:
104
+ - 0
105
+ hash: -1515901023488646711
96
106
  requirements: []
97
107
  rubyforge_project: elfproef
98
- rubygems_version: 1.8.17
108
+ rubygems_version: 1.8.11
99
109
  signing_key:
100
110
  specification_version: 3
101
111
  summary: Validation for Dutch bank account numbers and Citizen Service Numbers (BSN)
102
112
  test_files:
103
- - spec/elfproef_spec.rb
113
+ - spec/bank_account_validator_spec.rb
114
+ - spec/bsn_validator_spec.rb
104
115
  - spec/spec_helper.rb
@@ -1,160 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper'
2
-
3
- describe Elfproef do
4
- account_class = Class.new do
5
- include ActiveModel::Validations
6
- attr_accessor :account
7
- validates :account, :elfproef => { :allow_ing => true }
8
- end
9
-
10
- bank_only_class = Class.new do
11
- include ActiveModel::Validations
12
- attr_accessor :account
13
- validates :account, :elfproef => true
14
- end
15
-
16
- # Nine digets are not allowed
17
- it "tests account format" do
18
- Elfproef.elfproef(123456).should == false
19
- Elfproef.elfproef(1234567890).should == false
20
- Elfproef.elfproef('12345678a').should == false
21
- end
22
-
23
- # Invalid accounts will a value greather then 0
24
- it "tests invalid accounts" do
25
- Elfproef.elfproef(999999999).should == false
26
- Elfproef.elfproef('99.99.99.999').should == false
27
- Elfproef.elfproef('99 99 99 999').should == false
28
- end
29
-
30
- # Valid accounts will return 0
31
- it "tests valid accounts" do
32
- Elfproef.elfproef(123456789).should == true
33
- Elfproef.elfproef('12.34.56.789').should == true
34
- Elfproef.elfproef('12 34 56 789').should == true
35
- end
36
-
37
- it "tests valid ING accounts" do
38
- opts = { :allow_ing => true }
39
- Elfproef.elfproef(1234567, opts).should == true
40
- Elfproef.elfproef('1234567', opts).should == true
41
- end
42
-
43
- shared_examples_for "elfproef validations" do
44
- subject { account_class.new }
45
-
46
- it "fails when empty" do
47
- subject.should_not be_valid
48
- subject.errors[:account].should == errors
49
- end
50
-
51
- it "fails with an obviously wrong number" do
52
- subject.account = "12345678901"
53
- subject.should_not be_valid
54
- subject.errors[:account].should == errors
55
- end
56
-
57
- it "passes with a 7-diget ING number" do
58
- subject.account = "1234567"
59
- subject.should be_valid
60
- end
61
-
62
- it "passes with a 6-digit ING number" do
63
- subject.account = "123456"
64
- subject.should be_valid
65
- end
66
-
67
- it "passes with a 5-digit ING number" do
68
- subject.account = "12345"
69
- subject.should be_valid
70
- end
71
-
72
- it "passes with a 4-digit ING number" do
73
- subject.account = "1234"
74
- subject.should be_valid
75
- end
76
-
77
- it "passes with a 3-digit ING number" do
78
- subject.account = "123"
79
- subject.should be_valid
80
- end
81
-
82
- it "passes with a 2-digit ING number" do
83
- subject.account = "12"
84
- subject.should be_valid
85
- end
86
-
87
- it "passes with a 1-digit ING number" do
88
- subject.account = "1"
89
- subject.should be_valid
90
- end
91
-
92
- it "passes with a ING number starting with a P (from Postbank)" do
93
- subject.account = "P1234567"
94
- subject.should be_valid
95
- end
96
-
97
- it "passes with a valid 9-digit bank number" do
98
- subject.account = "123456789"
99
- subject.should be_valid
100
- end
101
-
102
- it "passes with a valid 10-digit bank number" do
103
- subject.account = "0123456789"
104
- subject.should be_valid
105
- end
106
-
107
- it "fails with an wrong bank number" do
108
- subject.account = "999999999"
109
- subject.should_not be_valid
110
- subject.errors[:account].should == errors
111
- end
112
- end
113
-
114
- shared_examples_for "elfproef, bank accounts only validations" do
115
- subject { bank_only_class.new }
116
-
117
- it "fails when empty" do
118
- subject.should_not be_valid
119
- subject.errors[:account].should == errors
120
- end
121
-
122
- it "fails with an obviously wrong number" do
123
- subject.account = "666"
124
- subject.should_not be_valid
125
- subject.errors[:account].should == errors
126
- end
127
-
128
- it "fails with a ING number" do
129
- subject.account = "1234567"
130
- subject.should_not be_valid
131
- subject.errors[:account].should == errors
132
- end
133
-
134
- it "passes with a valid 9-digit bank number" do
135
- subject.account = "123456789"
136
- subject.should be_valid
137
- end
138
-
139
- it "passes with a valid 10-digit bank number" do
140
- subject.account = "0123456789"
141
- subject.should be_valid
142
- end
143
-
144
- it "fails with an wrong bank number" do
145
- subject.account = "999999999"
146
- subject.should_not be_valid
147
- subject.errors[:account].should == errors
148
- end
149
- end
150
-
151
- describe "bank + ing validations" do
152
- let!(:errors) { [ "is not valid"] }
153
- it_should_behave_like "elfproef validations"
154
- end
155
-
156
- describe "bank only validations" do
157
- let!(:errors) { [ "is not valid"] }
158
- it_should_behave_like "elfproef, bank accounts only validations"
159
- end
160
- end