codice-fiscale 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/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in codice_fiscale.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,33 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard_options = {
5
+ :all_after_pass => false,
6
+ :all_on_start => false,
7
+ :bundler => true,
8
+ :notification => true,
9
+ :keep_failed => false,
10
+ :cli => "-c -f doc"
11
+ }
12
+
13
+ guard('rspec', guard_options) do
14
+ watch(%r{^spec/.+_spec\.rb$})
15
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
16
+ watch('spec/spec_helper.rb') { "spec" }
17
+
18
+ # Rails example
19
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
20
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
21
+ 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"] }
22
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
23
+ watch('config/routes.rb') { "spec/routing" }
24
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
25
+
26
+ # Capybara request specs
27
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
28
+
29
+ # Turnip features and steps
30
+ watch(%r{^spec/acceptance/(.+)\.feature$})
31
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
32
+ end
33
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Daniele Molteni
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # Codice fiscale
2
+
3
+ A ruby gem to support the calculation of the italian fiscal code ("Cofice fiscale"),
4
+ that is an ID assigned to each italian citizen by the "Agenzia delle entrate".
5
+
6
+ To calculate the fiscal code you need the following information: name, surname,
7
+ gender, birthdate and the birthplace. Read more on [wikipedia](http://en.wikipedia.org/wiki/Italian_fiscal_code_card).
8
+
9
+ ## Usage
10
+
11
+ ```ruby
12
+ require 'codice_fiscale'
13
+
14
+ CodiceFiscale.calculate 'mario', 'rossi', :male, Date.new(1987, 1, 1), 'italia', 'lc', 'Abbadia Lariana'
15
+
16
+ # RSSMRA87A01A005V
17
+ ```
18
+
19
+ ## City codes (Codici catastali)
20
+ As explained above, one of the information required to calculate the fiscal code is the birthplace.
21
+ If a person was born outside Italy, only the italian name of the county is required.
22
+ For example, an italian citizen born in France:
23
+
24
+ ```ruby
25
+ CodiceFiscale.calculate 'mario', 'rossi', :male, Date.new(1987, 1, 1), 'francia'
26
+ ```
27
+ If a person was born in Italy you have to specify the *code* of the province and the *name* of the city. These informations are actually contained in an XLS
28
+ document downloaded from [agenziaterritorio.it](http://www.agenziaterritorio.it/?id=721), converted to CSV and shipped with this gem.
29
+
30
+ **But what if you have your own table with all those codes?**
31
+
32
+ In this case, you can add a custom block that fetches the codes from your tables/files:
33
+
34
+
35
+ *config/initializers/codice_fiscale_initializer.rb*:
36
+
37
+ ```ruby
38
+ # Fetching the codes using ActiveRecord:
39
+
40
+ CodiceFiscale.config.country_code do |country_name|
41
+ Country.find_by_name(country_name).code
42
+ end
43
+
44
+ CodiceFiscale.config.city_code do |city_name, province_code|
45
+ City.in_italy.find_by_province_and_city(province_code, city_name).code
46
+ end
47
+ ```
48
+
49
+ ## Installation
50
+
51
+ I'm currently supporting only **ruby 1.9+**
52
+
53
+ Add this line to your application's Gemfile:
54
+
55
+ gem 'codice_fiscale'
56
+
57
+ And then execute:
58
+
59
+ $ bundle
60
+
61
+ ## Testing
62
+
63
+ I'm using RSpec + guard (+ growl for notifications)
64
+
65
+ $ bundle exec guard
66
+
67
+ ## Contributing
68
+
69
+ 1. Fork it
70
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
71
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
72
+ 4. Push to the branch (`git push origin my-new-feature`)
73
+ 5. Create new Pull Request
74
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/codice_fiscale/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Daniele Molteni"]
6
+ gem.email = ["dani.m.mobile@gmail.com"]
7
+ gem.description = %q{Calculate the italian fiscal code}
8
+ gem.summary = %q{Calculate the italian fiscal code}
9
+ gem.homepage = "https://github.com/daniele-m/codice_fiscale"
10
+ gem.platform = Gem::Platform::RUBY
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.name = "codice-fiscale"
16
+ gem.require_paths = ["lib"]
17
+ gem.version = CodiceFiscale::VERSION
18
+
19
+ gem.add_development_dependency 'rspec'
20
+ gem.add_development_dependency 'guard-rspec'
21
+ gem.add_development_dependency 'rb-fsevent', '~> 0.9.1'
22
+ # The growl app must be separately downloaded and installed
23
+ gem.add_development_dependency 'growl'
24
+ end
@@ -0,0 +1,98 @@
1
+ require 'rubygems'
2
+ require 'date'
3
+ require 'csv'
4
+ require 'codice_fiscale/version'
5
+ require 'codice_fiscale/alphabet'
6
+ require 'codice_fiscale/codes'
7
+ require 'codice_fiscale/configuration'
8
+
9
+ module CodiceFiscale
10
+ extend self
11
+
12
+ def calculate name, surname, gender, birthdate, country_name, province_code = nil, city_name = nil
13
+ code = birthplace_part country_name, city_name, province_code
14
+ return nil unless code
15
+ code = surname_part(surname) + name_part(name) + birthdate_part(birthdate, gender) + code
16
+ puts code
17
+ code + check_character(code)
18
+ end
19
+
20
+
21
+ # Methods to generate each part of the code
22
+
23
+ def surname_part surname
24
+ surname.upcase!
25
+ code = first_three_consonants surname
26
+ code << first_three_vocals(surname)
27
+ truncate_and_right_pad_with_three_x code
28
+ end
29
+
30
+ def name_part name
31
+ name.upcase!
32
+ consonants_of_name = consonants name
33
+ return consonants_of_name[0]+consonants_of_name[2..3] if consonants_of_name.size >= 4
34
+ code = first_three_consonants name
35
+ code << first_three_vocals(name)
36
+ truncate_and_right_pad_with_three_x code
37
+ end
38
+
39
+ def birthdate_part birthdate, gender
40
+ code = birthdate.year.to_s[2..3]
41
+ code << Codes.month_letter(birthdate.month)
42
+ day_part = gender.to_s.downcase[0] == 'f' ? birthdate.day + 40 : birthdate.day
43
+ code << "#{day_part}".rjust(2, '0')
44
+ end
45
+
46
+ def city_code city_name, province_code
47
+ return config.city_code.call(city_name, province_code) if config.city_code
48
+ Codes.city city_name, province_code
49
+ end
50
+
51
+ def country_code country_name
52
+ return config.country_code.call(country_name) if config.country_code
53
+ Codes.country country_name
54
+ end
55
+
56
+ def birthplace_part country_name, city_name = nil, province_code = nil
57
+ if %w[italia italy].include?(country_name.downcase.strip)
58
+ city_code city_name, province_code
59
+ else
60
+ country_code country_name
61
+ end
62
+ end
63
+
64
+ def check_character partial_fiscal_code
65
+ numeric_value = 0
66
+ partial_fiscal_code.split('').each_with_index do |chr, index|
67
+ numeric_value += ((index+1) % 2 == 0) ? Codes.even_character(chr) : Codes.odd_character(chr)
68
+ end
69
+ Codes.check_character numeric_value % 26
70
+ end
71
+
72
+
73
+ # Helper methods
74
+
75
+ # Intersect two strings or a string and an array of characters.
76
+ def intersects string_a, string_or_array_b
77
+ letters_a = string_a.split ''
78
+ letters_b = string_or_array_b.respond_to?(:split) ? string_or_array_b.split('') : string_or_array_b
79
+ selected_letters = letters_a.select { |letter| letters_b.include? letter }
80
+ selected_letters.join ''
81
+ end
82
+
83
+ def consonants string
84
+ intersects string, Alphabet.consonants
85
+ end
86
+
87
+ def first_three_consonants string
88
+ intersects(string, Alphabet.consonants)[0..2]
89
+ end
90
+
91
+ def first_three_vocals string
92
+ intersects(string, Alphabet.vocals)[0..2]
93
+ end
94
+
95
+ def truncate_and_right_pad_with_three_x string
96
+ string[0..2].ljust 3, 'X'
97
+ end
98
+ end
@@ -0,0 +1,17 @@
1
+ module CodiceFiscale
2
+ module Alphabet
3
+ extend self
4
+
5
+ def vocals
6
+ %w[A E I O U]
7
+ end
8
+
9
+ def consonants
10
+ letters - vocals
11
+ end
12
+
13
+ def letters
14
+ %w[A B C D E F G H I J K L M N O P Q R S T U V W X Y Z]
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,49 @@
1
+ module CodiceFiscale
2
+ module Codes
3
+ extend self
4
+
5
+ def config
6
+ CodiceFiscale.config
7
+ end
8
+
9
+ def month_letter month_number
10
+ decode = %w[A B C D E H L M P R S T]
11
+ month_number <= 0 ? nil : decode[month_number-1]
12
+ end
13
+
14
+ def city city_name, province_code
15
+ CSV.foreach config.city_codes_csv_path do |row|
16
+ if city_name.casecmp(row[3].strip) == 0 and province_code.casecmp(row[2].strip) == 0
17
+ return row[0].strip.upcase
18
+ end
19
+ end
20
+ nil
21
+ end
22
+
23
+ def country country_name
24
+ CSV.foreach config.country_codes_csv_path do |row|
25
+ return row[3].strip.upcase if country_name.casecmp(row[2].strip) == 0
26
+ end
27
+ nil
28
+ end
29
+
30
+ def odd_character character
31
+ decode = {'0' => 1, '1' => 0, '2' => 5, '3' => 7, '4' => 9, '5' => 13, '6' => 15, '7' => 17, '8' => 19, '9' => 21, 'A' => 1, 'B' => 0,
32
+ 'C' => 5, 'D' => 7, 'E' => 9, 'F' => 13, 'G' => 15, 'H' => 17, 'I' => 19, 'J' => 21, 'K' => 2, 'L' => 4, 'M' => 18, 'N' => 20,
33
+ 'O' => 11, 'P' => 3, 'Q' => 6, 'R' => 8, 'S' => 12, 'T' => 14, 'U' => 16, 'V' => 10, 'W' => 22, 'X' => 25, 'Y' => 24, 'Z' => 23}
34
+ decode[character.upcase]
35
+ end
36
+
37
+ def even_character character
38
+ decode = {'0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9, 'A' => 0, 'B' => 1,
39
+ 'C' => 2, 'D' => 3, 'E' => 4, 'F' => 5, 'G' => 6, 'H' => 7, 'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => 13,
40
+ 'O' => 14, 'P' => 15, 'Q' => 16, 'R' => 17, 'S' => 18, 'T' => 19, 'U' => 20, 'V' => 21, 'W' => 22, 'X' => 23, 'Y' => 24, 'Z' => 25}
41
+ decode[character.upcase]
42
+ end
43
+
44
+ def check_character number
45
+ decode = %w[A B C D E F G H I J K L M N O P Q R S T U V W X Y Z]
46
+ decode[number]
47
+ end
48
+ end
49
+ end
@@ -0,0 +1 @@
1
+ CODICE NAZIONALE,CODICE CATASTALE BELFIORE aggiornato al 1/9/1999 ora non pi in uso,PROVINCIA,DENOMINAZIONE COMUNE,ANNOTAZIONE,VARIAZIONE CODICE NAZAZIONALE,VARIAZIONE CODICE CATASTALE,VARIAZIONE PROVINCIA,VARIAZIONE DENOMINAZIONE DEL COMUNE,DATA COSTITUZIONE,DATA VARIAZIONE,,,,
@@ -0,0 +1 @@
1
+ CONTIN,SIGLA,DENOMINAZ,CODICE,DATAIST,DATASOP,CODRIF,DATAVARIAZ
@@ -0,0 +1,36 @@
1
+ module CodiceFiscale
2
+ class Configuration
3
+ def initialize
4
+ @options = default
5
+ end
6
+
7
+ def csv_folder
8
+ File.join File.dirname(__FILE__), 'codes'
9
+ end
10
+
11
+ def default
12
+ {
13
+ :city_codes_csv_path => "#{csv_folder}/city_codes.csv",
14
+ :country_codes_csv_path => "#{csv_folder}/country_codes.csv",
15
+ :city_code => nil,
16
+ :country_code => nil
17
+ }
18
+ end
19
+
20
+ def method_missing name, *args, &block
21
+ name = remove_final_equal_char(name).to_sym
22
+ return @options[name] if args.empty? and !block_given?
23
+ @options[name] = block_given? && block || args.first
24
+ end
25
+
26
+ def remove_final_equal_char string
27
+ parts = string.to_s.scan(/\A(.*)(\=)\z/).flatten
28
+ parts.empty? ? string : parts.first
29
+ end
30
+ end
31
+
32
+
33
+ def config
34
+ @config ||= Configuration.new
35
+ end
36
+ end
@@ -0,0 +1,3 @@
1
+ module CodiceFiscale
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1 @@
1
+ CODICE NAZIONALE,CODICE CATASTALE BELFIORE aggiornato al 1/9/1999 ora non pi in uso,PROVINCIA,DENOMINAZIONE COMUNE,ANNOTAZIONE,VARIAZIONE CODICE NAZAZIONALE,VARIAZIONE CODICE CATASTALE,VARIAZIONE PROVINCIA,VARIAZIONE DENOMINAZIONE DEL COMUNE,DATA COSTITUZIONE,DATA VARIAZIONE
@@ -0,0 +1 @@
1
+ CONTIN,SIGLA,DENOMINAZ,CODICE,DATAIST,DATASOP,CODRIF,DATAVARIAZ
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe CodiceFiscale::Alphabet do
4
+ describe '#letters' do
5
+ it 'is 26 long' do
6
+ subject.letters.size.should == 26
7
+ end
8
+
9
+ it 'return only upcased letters' do
10
+ subject.letters.each { |letter| letter.upcase.should == letter }
11
+ end
12
+ end
13
+
14
+ describe '#consonants' do
15
+ it 'is 21 long' do
16
+ subject.consonants.size.should == 21
17
+ end
18
+ end
19
+
20
+ describe '#vocals' do
21
+ it 'return only upcased letters' do
22
+ subject.letters.each { |letter| letter.upcase.should == letter }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe CodiceFiscale::Codes do
4
+ describe '#month_letter' do
5
+ context 'the given number is greater than 0 and less than 12' do
6
+ it 'return a letter' do
7
+ subject.month_letter(1).should == 'A'
8
+ end
9
+ end
10
+
11
+ context 'the given number is greater than 12' do
12
+ it 'return nil' do
13
+ subject.month_letter(13).should be_nil
14
+ end
15
+ end
16
+
17
+ context 'the given number is less than 1' do
18
+ it 'return nil' do
19
+ subject.month_letter(0).should be_nil
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,183 @@
1
+ require 'spec_helper'
2
+
3
+ describe CodiceFiscale do
4
+ before do
5
+ subject.config.city_codes_csv_path = "#{fixtures_path}/city_codes.csv"
6
+ subject.config.country_codes_csv_path = "#{fixtures_path}/country_codes.csv"
7
+ end
8
+
9
+ describe '#surname_part' do
10
+ it 'takes the first 3 consonants' do
11
+ subject.surname_part('molteni').should == 'MLT'
12
+ end
13
+
14
+ it 'is 3 chrs long' do
15
+ subject.surname_part('').size.should == 3
16
+ subject.surname_part('foobar').size.should == 3
17
+ end
18
+
19
+ context 'surname has only 1 consonant' do
20
+ it 'put the vocals after the consonants' do
21
+ subject.surname_part('oof').should == 'FOO'
22
+ end
23
+ end
24
+
25
+ context 'surname is less than 3 chrs long' do
26
+ it 'pad with the "X" character' do
27
+ subject.surname_part('m').should == 'MXX'
28
+ end
29
+ end
30
+ end
31
+
32
+
33
+ describe '#name_part' do
34
+ it 'is 3 chrs long' do
35
+ subject.name_part('').size.should == 3
36
+ subject.name_part('foobar').size.should == 3
37
+ end
38
+
39
+ context 'name has 4 or more consonants' do
40
+ it 'take the 1st the 3rd and the 4th' do
41
+ subject.name_part('danielino').should == 'DLN'
42
+ end
43
+ end
44
+
45
+ context "name has 3 or less consonants" do
46
+ it 'take the first 3 consonants' do
47
+ subject.name_part('daniele').should == 'DNL'
48
+ end
49
+ end
50
+
51
+ context 'name has 2 consonants' do
52
+ it 'put the vocals after the consonants' do
53
+ subject.name_part('bar').should == 'BRA'
54
+ end
55
+ end
56
+
57
+ context 'name is less than 3 chrs long' do
58
+ it 'pad with the "X" character' do
59
+ subject.name_part('d').should == 'DXX'
60
+ end
61
+ end
62
+ end
63
+
64
+
65
+ describe '#birthdate_part' do
66
+ let(:birthdate) { Date.new 1987, 12, 3 }
67
+ let(:male) { 'm' }
68
+ let(:female) { 'f' }
69
+
70
+ it 'start with the last 2 digit of the year' do
71
+ subject.birthdate_part(birthdate, male).should start_with '87'
72
+ end
73
+
74
+ describe 'the 3rd character' do
75
+ before { subject::Codes.stub(:month_letter).and_return('X') }
76
+
77
+ it('is the month code') { subject.birthdate_part(birthdate, male)[2].should == 'X' }
78
+ end
79
+
80
+ describe 'the last 2 character' do
81
+ context 'gender is male' do
82
+ it('is the birth day') { subject.birthdate_part(birthdate, male)[3..5].should == '03' }
83
+ end
84
+
85
+ context 'gender is female' do
86
+ it('is the birth day + 40') { subject.birthdate_part(birthdate, female)[3..5].should == '43' }
87
+ end
88
+ end
89
+ end
90
+
91
+
92
+ describe '#city_code' do
93
+ context 'the city and the provice are founded' do
94
+ it 'return the associated code' do
95
+ subject.city_code('Abbadia Lariana', 'LC').should == 'A005'
96
+ end
97
+ end
98
+
99
+ context 'the city and the provice are not founded' do
100
+ it 'return nil' do
101
+ subject.city_code('Winterfell', 'SO').should be_nil
102
+ end
103
+ end
104
+
105
+ context 'a block is configured to be called' do
106
+ before { subject.config.city_code { "foo" } }
107
+
108
+ it 'return the result of the block execution' do
109
+ subject.city_code('Lecco', 'LC').should == 'foo'
110
+ end
111
+ end
112
+ end
113
+
114
+
115
+ describe '#country_code' do
116
+ context 'the country is founded' do
117
+ it 'return the associated code' do
118
+ subject.country_code('francia').should == 'Z110'
119
+ end
120
+ end
121
+
122
+ context 'a block is configured to be called' do
123
+ before { subject.config.country_code { "bar" } }
124
+
125
+ it 'return the result of the block execution' do
126
+ subject.country_code('francia').should == 'bar'
127
+ end
128
+ end
129
+ end
130
+
131
+
132
+ describe '#birthplace_part' do
133
+ before do
134
+ subject.config.country_code = nil
135
+ subject.config.city_code = nil
136
+ end
137
+
138
+ context 'the country is Italy' do
139
+ it 'return the city_code' do
140
+ subject.birthplace_part('Italia', 'Abbadia Lariana', 'LC').should == 'A005'
141
+ end
142
+ end
143
+ end
144
+
145
+
146
+ describe '#check_character' do
147
+ it 'call #Codes.check_character and return its result' do
148
+ subject::Codes.should_receive :check_character
149
+ subject.check_character 'ABC'
150
+ end
151
+
152
+ it 'call #Codes.odd_character for odd positioned chars' do
153
+ subject::Codes.should_receive(:odd_character).exactly(2).and_return 1
154
+ subject.check_character 'ABC'
155
+ end
156
+
157
+ it 'call #Codes.even_character for odd positioned chars' do
158
+ subject::Codes.should_receive(:even_character).exactly(1).and_return 1
159
+ subject.check_character 'ABC'
160
+ end
161
+
162
+ it 'works!' do
163
+ subject.check_character('RSSMRA87A01A005').should == 'V'
164
+ end
165
+ end
166
+
167
+
168
+ describe '#calculate' do
169
+ context 'italian citizen' do
170
+ it 'return the expected code' do
171
+ params = ['mario', 'rossi', :male, Date.new(1987, 1, 1), 'italia', 'lc', 'Abbadia Lariana']
172
+ subject.calculate(*params).should == 'RSSMRA87A01A005V'
173
+ end
174
+ end
175
+
176
+ context 'return the expected code' do
177
+ it 'work' do
178
+ params = ['mario', 'rossi', :male, Date.new(1987, 1, 1), 'Albania']
179
+ subject.calculate(*params).should == 'RSSMRA87A01Z100H'
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,7 @@
1
+ def fixtures_path
2
+ File.expand_path '../fixtures', __FILE__
3
+ end
4
+
5
+ require File.expand_path '../../lib/codice_fiscale', __FILE__
6
+
7
+
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: codice-fiscale
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Daniele Molteni
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: guard-rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rb-fsevent
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.1
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.1
62
+ - !ruby/object:Gem::Dependency
63
+ name: growl
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: Calculate the italian fiscal code
79
+ email:
80
+ - dani.m.mobile@gmail.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - .gitignore
86
+ - Gemfile
87
+ - Guardfile
88
+ - LICENSE
89
+ - README.md
90
+ - Rakefile
91
+ - codice_fiscale.gemspec
92
+ - lib/codice_fiscale.rb
93
+ - lib/codice_fiscale/alphabet.rb
94
+ - lib/codice_fiscale/codes.rb
95
+ - lib/codice_fiscale/codes/city_codes.csv
96
+ - lib/codice_fiscale/codes/country_codes.csv
97
+ - lib/codice_fiscale/configuration.rb
98
+ - lib/codice_fiscale/version.rb
99
+ - spec/fixtures/city_codes.csv
100
+ - spec/fixtures/country_codes.csv
101
+ - spec/lib/codice_fiscale/alphabet_spec.rb
102
+ - spec/lib/codice_fiscale/codes_spec.rb
103
+ - spec/lib/codice_fiscale_spec.rb
104
+ - spec/spec_helper.rb
105
+ homepage: https://github.com/daniele-m/codice_fiscale
106
+ licenses: []
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ! '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 1.8.24
126
+ signing_key:
127
+ specification_version: 3
128
+ summary: Calculate the italian fiscal code
129
+ test_files:
130
+ - spec/fixtures/city_codes.csv
131
+ - spec/fixtures/country_codes.csv
132
+ - spec/lib/codice_fiscale/alphabet_spec.rb
133
+ - spec/lib/codice_fiscale/codes_spec.rb
134
+ - spec/lib/codice_fiscale_spec.rb
135
+ - spec/spec_helper.rb