activepesel 0.0.2 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +2 -2
- data/README.md +28 -1
- data/activepesel.gemspec +1 -1
- data/lib/activepesel.rb +1 -0
- data/lib/activepesel/pesel.rb +9 -5
- data/lib/activepesel/pesel_generator.rb +72 -0
- data/lib/activepesel/version.rb +1 -1
- data/test/pesel_attr_test.rb +5 -0
- data/test/pesel_generator_test.rb +46 -0
- data/test/pesel_test.rb +32 -0
- metadata +9 -6
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
A simple PESEL (polish personal ID number) validator and personal data extractor for Rails 3. Compatible with Ruby 1.9 (Tested with 1.9.3)
|
4
4
|
|
5
|
+
![](http://dl.dropbox.com/s/27p6gra4p0c8q0m/pesel.jpg)
|
6
|
+
|
5
7
|
Activepesel library is available as a gem. In your Gemfile add:
|
6
8
|
|
7
9
|
```ruby
|
@@ -39,6 +41,12 @@ The method returns ```Activepesel::PersonalData``` object which has the followin
|
|
39
41
|
date_of_birth:Date
|
40
42
|
sex:Integer
|
41
43
|
```
|
44
|
+
See the example:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
User.find(1).dads_pesel_personal_data => Activepesel::PersonalData(...)
|
48
|
+
```
|
49
|
+
|
42
50
|
|
43
51
|
Sex attribute can take 3 values. 1 - for men, 2 - for women, 9 - not applicable ([ISO/IEC 5218](http://en.wikipedia.org/wiki/ISO/IEC_5218))
|
44
52
|
|
@@ -46,7 +54,7 @@ For the invalid PESEL numbers the ```date_of_birth``` attribute is set to ```nil
|
|
46
54
|
|
47
55
|
# Saving personal data into database
|
48
56
|
|
49
|
-
It is a common
|
57
|
+
It is a common practice that you want to save the personal data extracted from the PESEL number to be able for example to query your records against all female persons. To do this you can use ActiveModel callbacks like in the example:
|
50
58
|
|
51
59
|
```ruby
|
52
60
|
class User < ActiveRecord::Base
|
@@ -81,6 +89,25 @@ pesel.personal_data => Activepesel::PersonalData(...)
|
|
81
89
|
pesel.date_of_birth => Wed, 02 Jun 1982
|
82
90
|
pesel.sex => 1
|
83
91
|
```
|
92
|
+
# Generating PESEL numbers
|
93
|
+
|
94
|
+
Since version 0.1.0 you can generate valid PESEL numbers for a given date of birth and sex of a person.
|
95
|
+
|
96
|
+
To generate one randomly picked PESEL number for let's say a male born on November 3rd 1975:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
# picks one random number for the given personal data
|
100
|
+
Pesel.generate(:one, :sex => 1, :date_of_birth => Date.new(1975,11,3))
|
101
|
+
````
|
102
|
+
|
103
|
+
To generate all (5000) PESEL numbers valid for a person of a given sex and date of birth for example a female born on May 20th 2010:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
# returns all possible numbers for the given personal data in a lexicographic order
|
107
|
+
Pesel.generate(:all, :sex => 2, :date_of_birth => "2010-05-20") # notice that you can pass a stringified date.
|
108
|
+
```
|
109
|
+
|
110
|
+
|
84
111
|
|
85
112
|
|
86
113
|
|
data/activepesel.gemspec
CHANGED
data/lib/activepesel.rb
CHANGED
data/lib/activepesel/pesel.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
module Activepesel
|
2
2
|
class Pesel
|
3
|
-
|
3
|
+
|
4
|
+
class << self
|
5
|
+
delegate :generate, :to => "Activepesel::PeselGenerator".to_sym
|
6
|
+
end
|
7
|
+
|
4
8
|
DIGIT_WEIGHTS = [1, 3, 7, 9, 1, 3 ,7, 9, 1, 3, 1].freeze
|
5
|
-
|
9
|
+
|
6
10
|
attr_reader :number
|
7
|
-
|
8
|
-
delegate :date_of_birth, :sex, :to => :personal_data
|
9
11
|
|
12
|
+
delegate :date_of_birth, :sex, :to => :personal_data
|
13
|
+
|
10
14
|
def initialize(number)
|
11
15
|
@number = number
|
12
16
|
end
|
@@ -20,7 +24,7 @@ module Activepesel
|
|
20
24
|
end
|
21
25
|
|
22
26
|
def personal_data
|
23
|
-
PersonalData.new(self)
|
27
|
+
PersonalData.new(self) if @number
|
24
28
|
end
|
25
29
|
|
26
30
|
private
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Activepesel
|
2
|
+
class PeselGenerator
|
3
|
+
|
4
|
+
SEX_CODES = {
|
5
|
+
1 => [1, 3, 5, 7, 9],
|
6
|
+
2 => [0, 2, 4, 6, 8]
|
7
|
+
}.freeze
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
def generate(*args)
|
12
|
+
raise(::ArgumentError, "Bad argument! You can pass :all or :one") unless [:all, :one].include?(args[0])
|
13
|
+
options = args.extract_options!
|
14
|
+
raise(::ArgumentError, "Date of birth can only be from range: (1800-01-01..2299-12-31)") if !options[:date_of_birth].respond_to?(:to_date) || !(Date.new(1800,1,1)..Date.new(2299,12,31)).include?(options[:date_of_birth].to_date)
|
15
|
+
raise(::ArgumentError, "Sex can only be set to 1 - males and 2 - females") if !options[:sex].respond_to?(:to_i) || ![1,2].include?(options[:sex].to_i)
|
16
|
+
send(args.first, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def one(options)
|
22
|
+
incomplete_pesel = "#{date_of_birth_code(options[:date_of_birth])}#{varying_codes[rand(998)]}#{sex_codes(options[:sex])[rand(4)]}"
|
23
|
+
Pesel.new("#{incomplete_pesel}#{control_digit(incomplete_pesel)}")
|
24
|
+
end
|
25
|
+
|
26
|
+
def all(options)
|
27
|
+
[].tap do |pesels|
|
28
|
+
varying_codes.each do |varying_code|
|
29
|
+
sex_codes(options[:sex]).each do |sex_code|
|
30
|
+
incomplete_pesel = "#{date_of_birth_code(options[:date_of_birth])}#{varying_code}#{sex_code}"
|
31
|
+
pesels << Pesel.new("#{incomplete_pesel}#{control_digit(incomplete_pesel)}")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def control_digit(incomplete_pesel)
|
38
|
+
digits = incomplete_pesel.split("").map(&:to_i)
|
39
|
+
(10 - Pesel::DIGIT_WEIGHTS[0..-2].each_with_index.inject(0){|sum, (factor, idx)| sum + factor * digits[idx]})%10
|
40
|
+
end
|
41
|
+
|
42
|
+
def sex_codes(sex)
|
43
|
+
SEX_CODES[sex.to_i]
|
44
|
+
end
|
45
|
+
|
46
|
+
def varying_codes
|
47
|
+
(0..999).to_a.map{|code| sprintf("%03d", code)}
|
48
|
+
end
|
49
|
+
|
50
|
+
def date_of_birth_code(date_of_birth)
|
51
|
+
[year_code(date_of_birth.to_date.year), month_code(date_of_birth.to_date.year, date_of_birth.to_date.month), day_code(date_of_birth.to_date.day)].join
|
52
|
+
end
|
53
|
+
|
54
|
+
def century(year)
|
55
|
+
year / 100
|
56
|
+
end
|
57
|
+
|
58
|
+
def year_code(year)
|
59
|
+
sprintf("%02d", year - 100 * century(year))
|
60
|
+
end
|
61
|
+
|
62
|
+
def month_code(year, month)
|
63
|
+
sprintf("%02d", month + PersonalData::DELTA[century(year)])
|
64
|
+
end
|
65
|
+
|
66
|
+
def day_code(day)
|
67
|
+
sprintf("%02d", day)
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/activepesel/version.rb
CHANGED
data/test/pesel_attr_test.rb
CHANGED
@@ -54,4 +54,9 @@ class PeselAttrTest < ActiveSupport::TestCase
|
|
54
54
|
assert_equal 2, users("22xx").mums_pesel_personal_data.sex
|
55
55
|
end
|
56
56
|
|
57
|
+
test "Personal data should be nil for nil Pesel attributes" do
|
58
|
+
user = User.create(:mums_pesel => nil)
|
59
|
+
assert_equal nil, user.mums_pesel_personal_data
|
60
|
+
end
|
61
|
+
|
57
62
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PeselGeneratorTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
test "PeselGenerator.generate with wrong args should raise a ArgumentError" do
|
6
|
+
assert_raise ArgumentError, "Bad argument! You can pass :all or :one" do
|
7
|
+
Activepesel::PeselGenerator.generate :foo, :sex =>1, :date_of_birth => Date.new(1982,6,2)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
test "PeselGenerator.generate with wrong date should raise a ArgumentError" do
|
12
|
+
assert_raise ArgumentError, "Date of birth can only be from range: (1800-01-01..2299-12-31)" do
|
13
|
+
Activepesel::PeselGenerator.generate :foo, :sex =>333, :date_of_birth => Date.new(1982,6,2)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
test "PeselGenerator.generate with wrong sex should raise a ArgumentError" do
|
18
|
+
assert_raise ArgumentError, "Sex can only be set to 1 - males and 2 - females" do
|
19
|
+
Activepesel::PeselGenerator.generate :foo, :sex =>333, :date_of_birth => Date.new(1982,6,2)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
test "PeselGenerator should generate valid pesel for 18XX's" do
|
24
|
+
assert_equal true, Activepesel::PeselGenerator.generate(:one, :sex =>1, :date_of_birth => Date.new(1807,2,15)).valid?
|
25
|
+
end
|
26
|
+
|
27
|
+
test "PeselGenerator should generate valid pesel for 19XX's" do
|
28
|
+
assert_equal true, Activepesel::PeselGenerator.generate(:one, :sex =>1, :date_of_birth => Date.new(1907,2,15)).valid?
|
29
|
+
end
|
30
|
+
|
31
|
+
test "PeselGenerator should generate valid pesel for 20XX's" do
|
32
|
+
assert_equal true, Activepesel::PeselGenerator.generate(:one, :sex =>1, :date_of_birth => Date.new(2007,2,15)).valid?
|
33
|
+
end
|
34
|
+
|
35
|
+
test "PeselGenerator should generate valid pesel for 21XX's" do
|
36
|
+
assert_equal true, Activepesel::PeselGenerator.generate(:one, :sex =>1, :date_of_birth => Date.new(2107,2,15)).valid?
|
37
|
+
end
|
38
|
+
|
39
|
+
test "PeselGenerator should generate valid pesel for 22XX's" do
|
40
|
+
assert_equal true, Activepesel::PeselGenerator.generate(:one, :sex =>1, :date_of_birth => Date.new(2207,2,15)).valid?
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
end
|
data/test/pesel_test.rb
CHANGED
@@ -30,5 +30,37 @@ class PeselTest < ActiveSupport::TestCase
|
|
30
30
|
assert_equal 9, Activepesel::Pesel.new("123123").personal_data.sex
|
31
31
|
end
|
32
32
|
|
33
|
+
test "Pesel.generate :all should return 5000 valid male pesel numbers" do
|
34
|
+
pesels = Activepesel::Pesel.generate(:all, :sex => 1, :date_of_birth => Date.new(1982,6,2))
|
35
|
+
assert_equal 5000, pesels.size
|
36
|
+
assert_equal true, !pesels.map(&:valid?).include?(false)
|
37
|
+
assert_equal nil, pesels.map(&:sex).detect{|t| t!=1}
|
38
|
+
assert_equal nil, pesels.map(&:date_of_birth).detect{|t| t!=Date.new(1982,6,2)}
|
39
|
+
end
|
40
|
+
|
41
|
+
test "Pesel.generate :all should return 5000 valid female pesel numbers" do
|
42
|
+
pesels = Activepesel::Pesel.generate(:all, :sex => 2, :date_of_birth => Date.new(1982,6,2))
|
43
|
+
assert_equal 5000, pesels.size
|
44
|
+
assert_equal true, !pesels.map(&:valid?).include?(false)
|
45
|
+
assert_equal nil, pesels.map(&:sex).detect{|t| t!=2}
|
46
|
+
assert_equal nil, pesels.map(&:date_of_birth).detect{|t| t!=Date.new(1982,6,2)}
|
47
|
+
end
|
48
|
+
|
49
|
+
test "Pesel.generate :one should return one male randomly picked from the pesel pool pesel number" do
|
50
|
+
pesel = Activepesel::Pesel.generate(:one, :sex => 1, :date_of_birth => Date.new(1982,6,2))
|
51
|
+
assert_equal true, pesel.valid?
|
52
|
+
assert_equal 1, pesel.sex
|
53
|
+
assert_equal Date.new(1982,6,2), pesel.date_of_birth
|
54
|
+
end
|
55
|
+
|
56
|
+
test "Pesel.generate :one should return one female randomly picked from the pesel pool pesel number" do
|
57
|
+
pesel = Activepesel::Pesel.generate(:one, :sex => 2, :date_of_birth => Date.new(1982,6,2))
|
58
|
+
assert_equal true, pesel.valid?
|
59
|
+
assert_equal 2, pesel.sex
|
60
|
+
assert_equal Date.new(1982,6,2), pesel.date_of_birth
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
|
33
65
|
|
34
66
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activepesel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,24 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 3.
|
21
|
+
version: 3.0.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 3.
|
29
|
+
version: 3.0.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: sqlite3
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -64,6 +64,7 @@ files:
|
|
64
64
|
- lib/activepesel/personal_data.rb
|
65
65
|
- lib/activepesel/pesel.rb
|
66
66
|
- lib/activepesel/pesel_attr.rb
|
67
|
+
- lib/activepesel/pesel_generator.rb
|
67
68
|
- lib/activepesel/version.rb
|
68
69
|
- lib/tasks/activepesel_tasks.rake
|
69
70
|
- test/activepesel_test.rb
|
@@ -105,6 +106,7 @@ files:
|
|
105
106
|
- test/dummy/test/fixtures/users.yml
|
106
107
|
- test/dummy/test/unit/user_test.rb
|
107
108
|
- test/pesel_attr_test.rb
|
109
|
+
- test/pesel_generator_test.rb
|
108
110
|
- test/pesel_test.rb
|
109
111
|
- test/pesel_validator_test.rb
|
110
112
|
- test/test_helper.rb
|
@@ -179,6 +181,7 @@ test_files:
|
|
179
181
|
- test/dummy/test/fixtures/users.yml
|
180
182
|
- test/dummy/test/unit/user_test.rb
|
181
183
|
- test/pesel_attr_test.rb
|
184
|
+
- test/pesel_generator_test.rb
|
182
185
|
- test/pesel_test.rb
|
183
186
|
- test/pesel_validator_test.rb
|
184
187
|
- test/test_helper.rb
|