resident 0.0.9
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/.gemtest +0 -0
- data/MIT-LICENSE +19 -0
- data/README.rdoc +57 -0
- data/lib/national_identification_number/base.rb +31 -0
- data/lib/national_identification_number/finnish.rb +53 -0
- data/lib/national_identification_number/swedish.rb +105 -0
- data/lib/national_identification_number.rb +2 -0
- data/lib/resident.rb +1 -0
- data/spec/national_identification_number/base_spec.rb +74 -0
- data/spec/national_identification_number/finnish_spec.rb +60 -0
- data/spec/national_identification_number/swedish_spec.rb +147 -0
- metadata +98 -0
data/.gemtest
ADDED
File without changes
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2011 Bukowskis.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
= Resident
|
2
|
+
|
3
|
+
Validates a National Identification Number (See http://en.wikipedia.org/wiki/National_identification_number).
|
4
|
+
There are some 62 countries that have this type of number.
|
5
|
+
This gem currently only supports Swedish (Personnummer) and Finnish (Henkilöasiakkaat) ones.
|
6
|
+
|
7
|
+
There is a special focus on identifying these numbers robustly (i.e. you can safely validate a param[:number] directly, or cleanup your database by running every non-normalized value through this gem).
|
8
|
+
|
9
|
+
== Installation
|
10
|
+
|
11
|
+
gem install resident
|
12
|
+
|
13
|
+
== Usage
|
14
|
+
|
15
|
+
Really, you can just use <tt>valid?</tt> and <tt>to_s</tt> like so:
|
16
|
+
|
17
|
+
require 'resident'
|
18
|
+
|
19
|
+
number = NationalIdentificationNumber::Swedish.new('0501261853')
|
20
|
+
|
21
|
+
number.valid? #=> true
|
22
|
+
number.to_s #=> "050126-1853"
|
23
|
+
|
24
|
+
Please have a look at the specs to see how the national identification numbers of various countries are handled.
|
25
|
+
|
26
|
+
An example of robustness:
|
27
|
+
|
28
|
+
NationalIdentificationNumber::Swedish.new("19050126-185d3\n").to_s => "050126-1853"
|
29
|
+
|
30
|
+
== License
|
31
|
+
|
32
|
+
Some marked parts of the code are inspired or taken from MIT licensed code of
|
33
|
+
|
34
|
+
* Peter Hellberg https://github.com/c7/personnummer/blob/master/lib/personnummer.rb
|
35
|
+
* Henrik Nyh http://henrik.nyh.se
|
36
|
+
|
37
|
+
Other than that you got:
|
38
|
+
|
39
|
+
Copyright (c) 2011 Bukowskis.
|
40
|
+
|
41
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
42
|
+
of this software and associated documentation files (the "Software"), to deal
|
43
|
+
in the Software without restriction, including without limitation the rights
|
44
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
45
|
+
copies of the Software, and to permit persons to whom the Software is
|
46
|
+
furnished to do so, subject to the following conditions:
|
47
|
+
|
48
|
+
The above copyright notice and this permission notice shall be included in
|
49
|
+
all copies or substantial portions of the Software.
|
50
|
+
|
51
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
52
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
53
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
54
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
55
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
56
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
57
|
+
THE SOFTWARE.
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module NationalIdentificationNumber
|
4
|
+
class Base
|
5
|
+
|
6
|
+
def initialize(number)
|
7
|
+
@number = number
|
8
|
+
repair
|
9
|
+
validate
|
10
|
+
end
|
11
|
+
|
12
|
+
def valid?
|
13
|
+
!!@valid
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
@number
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def repair
|
23
|
+
@number = @number.to_s.upcase.gsub(/\s/, '')
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate
|
27
|
+
raise 'You need to implement at least this method in subclasses.'
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'national_identification_number/base'
|
2
|
+
|
3
|
+
module NationalIdentificationNumber
|
4
|
+
class Finnish < Base
|
5
|
+
|
6
|
+
CHECKSUMS = %w{ 0 1 2 3 4 5 6 7 8 9 A B C D E F H J K L M N P R S T U V W X Y }
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
def repair
|
11
|
+
super
|
12
|
+
if @number.match(/(\d{6})(\-{0,1})(\d{3})([#{CHECKSUMS}]{1})/)
|
13
|
+
@number = "#{$1}-#{$3}#{$4}"
|
14
|
+
else
|
15
|
+
@number.gsub!(/[^#{CHECKSUMS}\-\+]/, '')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate
|
20
|
+
if @number.match(/(\d{2})(\d{2})(\d{2})([\-\+A]{0,1})(\d{3})([#{CHECKSUMS}]{1})/)
|
21
|
+
checksum = self.class.calculate_checksum("#{$1}#{$2}#{$3}#{$5}")
|
22
|
+
if checksum == $6
|
23
|
+
|
24
|
+
day = $1.to_i
|
25
|
+
month = $2.to_i
|
26
|
+
year = $3.to_i
|
27
|
+
divider ||= $4 ||'-'
|
28
|
+
serial = $5.to_i
|
29
|
+
|
30
|
+
century = case divider
|
31
|
+
when '+' then 1800
|
32
|
+
when 'A' then 2000
|
33
|
+
else 1900
|
34
|
+
end
|
35
|
+
|
36
|
+
begin
|
37
|
+
Date.parse("#{century+year}-#{month}-#{day}")
|
38
|
+
@valid = true
|
39
|
+
@number = ("#{$1}#{$2}#{$3}#{divider}#{$5}#{checksum}")
|
40
|
+
rescue ArgumentError
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def self.calculate_checksum(number)
|
49
|
+
CHECKSUMS[number.to_i % 31]
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'national_identification_number/base'
|
2
|
+
|
3
|
+
module NationalIdentificationNumber
|
4
|
+
# Inspired by https://github.com/c7/personnummer/blob/master/lib/personnummer.rb
|
5
|
+
# Copyright (c) 2008 Peter Hellberg MIT
|
6
|
+
class Swedish < Base
|
7
|
+
|
8
|
+
attr_reader :date # used for testing
|
9
|
+
|
10
|
+
# Generator for valid Swedish personnummer: http://en.wikipedia.org/wiki/Personal_identity_number_(Sweden)
|
11
|
+
# By Henrik Nyh <http://henrik.nyh.se> 2009-01-29 under the MIT license.
|
12
|
+
def self.generate(date=nil, serial=nil)
|
13
|
+
date ||= Date.new(1900+rand(100), 1+rand(12), 1+rand(28))
|
14
|
+
serial = serial ? serial.to_s : format("%03d", rand(999)+1) # 001-999
|
15
|
+
date_part = date.strftime('%y%m%d')
|
16
|
+
pnr = [date_part, serial].join
|
17
|
+
digits = []
|
18
|
+
pnr.split('').each_with_index do |n,i|
|
19
|
+
digits << n.to_i * (2 - i % 2)
|
20
|
+
end
|
21
|
+
sum = digits.join.split('').inject(0) {|sum,digit| sum + digit.to_i }
|
22
|
+
checksum = 10 - sum % 10
|
23
|
+
checksum = 0 if checksum == 10
|
24
|
+
"#{date_part}-#{serial}#{checksum}"
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def repair
|
30
|
+
super
|
31
|
+
if @number.match(/\A(\d{0}|\d{2})(\d{6})(\-{0,1})(\d{4})\Z/)
|
32
|
+
@number = "#{$2}-#{$4}"
|
33
|
+
else
|
34
|
+
@number.gsub!(/[^\d\-\+]/, '')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def validate
|
39
|
+
if @number.match(/(\d{2})(\d{2})(\d{2})([\-\+]{0,1})(\d{3})(\d{1})/)
|
40
|
+
checksum = self.class.luhn_algorithm("#{$1}#{$2}#{$3}#{$5}")
|
41
|
+
if checksum == $6.to_i
|
42
|
+
|
43
|
+
year = $1.to_i
|
44
|
+
month = $2.to_i
|
45
|
+
day = $3.to_i
|
46
|
+
divider ||= $4 ||'-'
|
47
|
+
serial = $5.to_i
|
48
|
+
|
49
|
+
today = Date.today
|
50
|
+
if year <= (today.year-2000) && divider == '-'
|
51
|
+
century = 2000
|
52
|
+
elsif year <= (today.year-2000) && divider == '+'
|
53
|
+
century = 1900
|
54
|
+
elsif divider == '+'
|
55
|
+
century = 1800
|
56
|
+
else
|
57
|
+
century = 1900
|
58
|
+
end
|
59
|
+
|
60
|
+
begin
|
61
|
+
@date = Date.parse("#{century+year}-#{month}-#{day}")
|
62
|
+
@valid = true
|
63
|
+
@number = ("#{$1}#{$2}#{$3}#{divider}#{$5}#{checksum}")
|
64
|
+
rescue ArgumentError
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def self.luhn_algorithm(number)
|
73
|
+
multiplications = []
|
74
|
+
number.split(//).each_with_index do |digit, i|
|
75
|
+
if i % 2 == 0
|
76
|
+
multiplications << digit.to_i*2
|
77
|
+
else
|
78
|
+
multiplications << digit.to_i
|
79
|
+
end
|
80
|
+
end
|
81
|
+
sum = 0
|
82
|
+
multiplications.each do |number|
|
83
|
+
number.to_s.each_byte do |character|
|
84
|
+
sum += character.chr.to_i
|
85
|
+
end
|
86
|
+
end
|
87
|
+
if sum % 10 == 0
|
88
|
+
control_digit = 0
|
89
|
+
else
|
90
|
+
control_digit = (sum / 10 + 1) * 10 - sum
|
91
|
+
end
|
92
|
+
control_digit
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
if $0 == __FILE__
|
99
|
+
# Randomize every part
|
100
|
+
puts Bukowskis::NationalIdentificationNumber::Swedish.generate
|
101
|
+
# Use given date, randomize serial
|
102
|
+
puts Bukowskis::NationalIdentificationNumber::Swedish.generate(Date.new(1975,1,1))
|
103
|
+
# Use given date and serial, calculate checksum
|
104
|
+
puts Bukowskis::NationalIdentificationNumber::Swedish.generate(Date.new(1975,1,1), 123)
|
105
|
+
end
|
data/lib/resident.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'national_identification_number'
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'resident'
|
3
|
+
|
4
|
+
include NationalIdentificationNumber
|
5
|
+
|
6
|
+
class TestBaseChild < NationalIdentificationNumber::Base
|
7
|
+
def set_valid_to_nil
|
8
|
+
@valid = nil
|
9
|
+
end
|
10
|
+
protected
|
11
|
+
def validate
|
12
|
+
@valid = 'validates_to_true'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe Base, 'new' do
|
17
|
+
|
18
|
+
it "should instantiate correctly" do
|
19
|
+
TestBaseChild.new('12345').should be_an_instance_of TestBaseChild
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should repair on initialization" do
|
23
|
+
TestBaseChild.new(' 12345abc ').to_s.should == '12345ABC'
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should validate on initialization" do
|
27
|
+
lambda { NationalIdentificationNumber::Base.new('12345') }.should raise_error(RuntimeError, 'You need to implement at least this method in subclasses.')
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
describe Base, 'valid?' do
|
33
|
+
|
34
|
+
it "should return true if it is valid" do
|
35
|
+
TestBaseChild.new('12345abc').should be_valid
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return true if it is valid" do
|
39
|
+
base = TestBaseChild.new('12345abc')
|
40
|
+
base.set_valid_to_nil
|
41
|
+
base.should_not be_valid
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe Base, 'to_s' do
|
47
|
+
|
48
|
+
it "should return the number" do
|
49
|
+
TestBaseChild.new('12345ABC').to_s.should == '12345ABC'
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
describe Base, 'repair' do
|
55
|
+
|
56
|
+
it "should be a protected method" do
|
57
|
+
lambda { TestBaseChild.new('12345').repair }.should raise_error NoMethodError
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should strip whitespaces and capitalize everything" do
|
61
|
+
TestBaseChild.new(' 123 45 abc %&/ ').to_s.should == '12345ABC%&/'
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should make it a string" do
|
65
|
+
TestBaseChild.new(:symbol).to_s.should == 'SYMBOL'
|
66
|
+
TestBaseChild.new(1234).to_s.should == '1234'
|
67
|
+
TestBaseChild.new(nil).to_s.should == ''
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should strip newlines and tabs" do
|
71
|
+
TestBaseChild.new("one\ntwo\tthree\n").to_s.should == 'ONETWOTHREE'
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'resident'
|
3
|
+
|
4
|
+
include NationalIdentificationNumber
|
5
|
+
|
6
|
+
describe Finnish, 'valid?' do
|
7
|
+
|
8
|
+
it "should recognize valid numbers" do
|
9
|
+
Finnish.new('311280-999J').should be_valid
|
10
|
+
Finnish.new('131052-308T').should be_valid
|
11
|
+
Finnish.new('290164-862u').should be_valid
|
12
|
+
Finnish.new('270368A172X').should be_valid
|
13
|
+
Finnish.new('310145A586a').should be_valid
|
14
|
+
Finnish.new('080266+183P').should be_valid
|
15
|
+
Finnish.new('290248+145c').should be_valid
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should recognize invalid numbers" do
|
19
|
+
Finnish.new('671301A172V').should_not be_valid # valid checksum, invalid month
|
20
|
+
Finnish.new('830231A172M').should_not be_valid # valid checksum, invalid day
|
21
|
+
Finnish.new('311180-999J').should_not be_valid
|
22
|
+
Finnish.new('131052-308S').should_not be_valid
|
23
|
+
Finnish.new('290164X862U').should_not be_valid
|
24
|
+
Finnish.new('670368A172X').should_not be_valid
|
25
|
+
Finnish.new('310145--586A').should_not be_valid
|
26
|
+
Finnish.new('asdf').should_not be_valid
|
27
|
+
Finnish.new('1234567890').should_not be_valid
|
28
|
+
Finnish.new('0000000000000').should_not be_valid
|
29
|
+
Finnish.new('000000-0000').should_not be_valid
|
30
|
+
Finnish.new('').should_not be_valid
|
31
|
+
Finnish.new(1234567890).should_not be_valid
|
32
|
+
Finnish.new(:really_bad_input_value).should_not be_valid
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
describe Finnish, 'to_s' do
|
38
|
+
|
39
|
+
it "should repair missing dashes, even if the number is invalid" do
|
40
|
+
Finnish.new('311280999K').to_s.should == '311280-999K'
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should return the number normalized if the number is valid" do
|
44
|
+
Finnish.new('311280999J').to_s.should == '311280-999J'
|
45
|
+
Finnish.new('270368A172X ').to_s.should == '270368A172X'
|
46
|
+
Finnish.new('xx270368A172X ').to_s.should == '270368A172X'
|
47
|
+
Finnish.new('xxx270368A172Xt ').to_s.should == '270368A172X'
|
48
|
+
Finnish.new('\t050126-1853').to_s.should == '050126-1853'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should always be injection safe, valid or not" do
|
52
|
+
Finnish.new(%Q{270368"A172 \tX}).to_s.should == '270368A172X'
|
53
|
+
Finnish.new(%Q{270368"A172\tX\n\n}).to_s.should == '270368A172X'
|
54
|
+
Finnish.new(%Q{270368"A172X}).to_s.should == '270368A172X'
|
55
|
+
Finnish.new(%Q{270368A<172X}).to_s.should == '270368A172X'
|
56
|
+
Finnish.new(%Q{270368A'172X}).to_s.should == '270368A172X'
|
57
|
+
Finnish.new(%Q{270368A>172X}).to_s.should == '270368A172X'
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'resident'
|
3
|
+
|
4
|
+
include NationalIdentificationNumber
|
5
|
+
|
6
|
+
describe Swedish, '.generate' do
|
7
|
+
|
8
|
+
it "should generate valid numbers" do
|
9
|
+
50.times { Swedish.new(Swedish.generate).should be_valid } # I know, it feels weird :)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
describe Swedish, 'valid?' do
|
15
|
+
|
16
|
+
it "should recognize valid numbers" do
|
17
|
+
Swedish.new("19180123-2669").should be_valid
|
18
|
+
Swedish.new("00180123-2669").should be_valid
|
19
|
+
Swedish.new("000180123-2669").should be_valid
|
20
|
+
Swedish.new("050126-1853").should be_valid
|
21
|
+
Swedish.new("0asdfghj501261853").should be_valid
|
22
|
+
Swedish.new("050112-2451").should be_valid
|
23
|
+
Swedish.new("450202-6950").should be_valid
|
24
|
+
Swedish.new("19450202-6950").should be_valid
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should recognize invalid numbers" do
|
28
|
+
Swedish.new("991301-1236").should_not be_valid # valid checksum, invalid month
|
29
|
+
Swedish.new("830231-5554").should_not be_valid # valid checksum, invalid day
|
30
|
+
Swedish.new("050112--2451").should_not be_valid
|
31
|
+
Swedish.new("123456-1239").should_not be_valid
|
32
|
+
Swedish.new("180123-2668").should_not be_valid
|
33
|
+
Swedish.new("150D1261853").should_not be_valid
|
34
|
+
Swedish.new("750112-2451").should_not be_valid
|
35
|
+
Swedish.new("123").should_not be_valid
|
36
|
+
Swedish.new("000000-0000").should_not be_valid
|
37
|
+
Swedish.new("0000000000").should_not be_valid
|
38
|
+
Swedish.new("asdfghj").should_not be_valid
|
39
|
+
Swedish.new("").should_not be_valid
|
40
|
+
Swedish.new(12345678).should_not be_valid
|
41
|
+
Swedish.new(:really_bad_input).should_not be_valid
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe Swedish, 'to_s' do
|
47
|
+
|
48
|
+
it "should repair missing dashes and a superfluous century, even if the number is invalid" do
|
49
|
+
Swedish.new('1234561239').to_s.should == '123456-1239'
|
50
|
+
Swedish.new('123456-1239').to_s.should == '123456-1239'
|
51
|
+
Swedish.new("191234561239").to_s.should == '123456-1239'
|
52
|
+
Swedish.new("19123456-1239").to_s.should == '123456-1239'
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return the number normalized if the number is valid" do
|
56
|
+
Swedish.new('0501261853').to_s.should == '050126-1853'
|
57
|
+
Swedish.new('050126-1853').to_s.should == '050126-1853'
|
58
|
+
Swedish.new("190501261853").to_s.should == '050126-1853'
|
59
|
+
Swedish.new("19050126-1853").to_s.should == '050126-1853'
|
60
|
+
Swedish.new("19050126-185d3").to_s.should == '050126-1853'
|
61
|
+
Swedish.new("19050126-185d3\n").to_s.should == '050126-1853'
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should always be injection safe, valid or not" do
|
65
|
+
Swedish.new(" 180 123 - 2669 \n\n\t").to_s.should == '180123-2669'
|
66
|
+
Swedish.new(" 180 123 - 2669 \n").to_s.should == '180123-2669'
|
67
|
+
Swedish.new(%Q{180123-"2669}).to_s.should == '180123-2669'
|
68
|
+
Swedish.new(%Q{180123-<2669}).to_s.should == '180123-2669'
|
69
|
+
Swedish.new(%Q{1801D23-'2669}).to_s.should == '180123-2669'
|
70
|
+
Swedish.new(%Q{180s123->2669}).to_s.should == '180123-2669'
|
71
|
+
Swedish.new(%Q{19180s123->2669}).to_s.should == '180123-2669'
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe Swedish, 'date' do # For testing only, no public API
|
77
|
+
|
78
|
+
it "should recognize babies born today" do
|
79
|
+
today = Date.today.strftime("%y%m%d")
|
80
|
+
born_today = Swedish.new("#{today}-000#{Swedish.luhn_algorithm("#{today}000")}")
|
81
|
+
born_today.should be_valid
|
82
|
+
born_today.date.should == Date.today
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should recognize babies born yesterday" do
|
86
|
+
today = (Date.today - 1).strftime("%y%m%d")
|
87
|
+
born_yesterday = Swedish.new("#{today}-000#{Swedish.luhn_algorithm("#{today}000")}")
|
88
|
+
born_yesterday.should be_valid
|
89
|
+
born_yesterday.date.should == (Date.today - 1)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should recognize people born in the year 2000" do
|
93
|
+
beginning_of_year = Swedish.new("000101-0008")
|
94
|
+
beginning_of_year.should be_valid
|
95
|
+
beginning_of_year.date.should == Date.new(2000, 1, 1)
|
96
|
+
leap_year = Swedish.new("000229-0005") # 2000 was a leap year, 1900 not
|
97
|
+
leap_year.should be_valid
|
98
|
+
leap_year.date.should == Date.new(2000, 2, 29)
|
99
|
+
end_of_year = Swedish.new("001231-0009")
|
100
|
+
end_of_year.should be_valid
|
101
|
+
end_of_year.date.should == Date.new(2000, 12, 31)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should recognize people born in the year 1999" do
|
105
|
+
beginning_of_year = Swedish.new("990101-0000")
|
106
|
+
beginning_of_year.should be_valid
|
107
|
+
beginning_of_year.date.should == Date.new(1999, 1, 1)
|
108
|
+
end_of_year = Swedish.new("991231-0001")
|
109
|
+
end_of_year.should be_valid
|
110
|
+
end_of_year.date.should == Date.new(1999, 12, 31)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should recognize all other people less than 100 years old" do
|
114
|
+
will_turn_99_this_year = Date.new(Date.today.year - 99, 12, 31).strftime("%y%m%d")
|
115
|
+
soon_99 = Swedish.new("#{will_turn_99_this_year}-000#{Swedish.luhn_algorithm("#{will_turn_99_this_year}000")}")
|
116
|
+
soon_99.should be_valid
|
117
|
+
soon_99.date.should == Date.new(Date.today.year - 99, 12, 31)
|
118
|
+
turned_99_this_year = Date.new(Date.today.year - 99, 1, 1).strftime("%y%m%d")
|
119
|
+
already_99 = Swedish.new("#{turned_99_this_year}-000#{Swedish.luhn_algorithm("#{turned_99_this_year}000")}")
|
120
|
+
already_99.should be_valid
|
121
|
+
already_99.date.should == Date.new(Date.today.year - 99, 1, 1)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should recognize people that turn 100 years in this year" do
|
125
|
+
will_turn_100_this_year = Date.new(Date.today.year - 100, 12, 31).strftime("%y%m%d")
|
126
|
+
soon_100 = Swedish.new("#{will_turn_100_this_year}+000#{Swedish.luhn_algorithm("#{will_turn_100_this_year}000")}")
|
127
|
+
soon_100.should be_valid
|
128
|
+
soon_100.date.should == Date.new(Date.today.year - 100, 12, 31)
|
129
|
+
turned_100_this_year = Date.new(Date.today.year - 100, 1, 1).strftime("%y%m%d")
|
130
|
+
already_100 = Swedish.new("#{turned_100_this_year}+000#{Swedish.luhn_algorithm("#{turned_100_this_year}000")}")
|
131
|
+
already_100.should be_valid
|
132
|
+
already_100.date.should == Date.new(Date.today.year - 100, 1, 1)
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should recognize people older than 100 years born after 1900" do
|
136
|
+
normal = Swedish.new("010101+0007")
|
137
|
+
normal.should be_valid
|
138
|
+
normal.date.should == Date.new(1901, 1, 1)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should recognize people older than 100 years born before 1900" do
|
142
|
+
normal = Swedish.new("991231+0001")
|
143
|
+
normal.should be_valid
|
144
|
+
normal.date.should == Date.new(1899, 12, 31)
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: resident
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 13
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 9
|
10
|
+
version: 0.0.9
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Bukowskis
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-12-19 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
description:
|
36
|
+
email:
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README.rdoc
|
43
|
+
- MIT-LICENSE
|
44
|
+
files:
|
45
|
+
- lib/national_identification_number/base.rb
|
46
|
+
- lib/national_identification_number/finnish.rb
|
47
|
+
- lib/national_identification_number/swedish.rb
|
48
|
+
- lib/national_identification_number.rb
|
49
|
+
- lib/resident.rb
|
50
|
+
- MIT-LICENSE
|
51
|
+
- README.rdoc
|
52
|
+
- .gemtest
|
53
|
+
- spec/national_identification_number/base_spec.rb
|
54
|
+
- spec/national_identification_number/finnish_spec.rb
|
55
|
+
- spec/national_identification_number/swedish_spec.rb
|
56
|
+
has_rdoc: true
|
57
|
+
homepage: http://github.com/bukowskis/national_identification_number/
|
58
|
+
licenses:
|
59
|
+
- MIT-LICENSE
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options:
|
62
|
+
- --main
|
63
|
+
- README.rdoc
|
64
|
+
- --charset=UTF-8
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 57
|
74
|
+
segments:
|
75
|
+
- 1
|
76
|
+
- 8
|
77
|
+
- 7
|
78
|
+
version: 1.8.7
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 1.5.3
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: Validate National Identification Numbers.
|
95
|
+
test_files:
|
96
|
+
- spec/national_identification_number/base_spec.rb
|
97
|
+
- spec/national_identification_number/finnish_spec.rb
|
98
|
+
- spec/national_identification_number/swedish_spec.rb
|