codice-fiscale 0.0.5 → 0.0.6

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.
@@ -21,4 +21,7 @@ Gem::Specification.new do |gem|
21
21
  gem.add_development_dependency 'rb-fsevent', '~> 0.9.1'
22
22
  # The growl app must be separately downloaded and installed
23
23
  gem.add_development_dependency 'growl'
24
+
25
+ gem.add_dependency 'active_support'
26
+ gem.add_dependency 'activemodel'
24
27
  end
@@ -1,108 +1,21 @@
1
1
  require 'rubygems'
2
2
  require 'date'
3
3
  require 'csv'
4
+ require 'active_model'
5
+ require 'active_support/core_ext/object/blank'
6
+ require 'active_support/core_ext/module/delegation'
4
7
  require 'codice_fiscale/version'
5
- require 'codice_fiscale/alphabet'
6
- require 'codice_fiscale/codes'
7
8
  require 'codice_fiscale/configuration'
9
+ require 'codice_fiscale/helpers'
10
+ require 'codice_fiscale/codes'
11
+ require 'codice_fiscale/alphabet'
12
+ require 'codice_fiscale/italian_citizen'
13
+ require 'codice_fiscale/fiscal_code'
8
14
 
9
15
  module CodiceFiscale
10
- extend self
11
-
12
- def calculate params
13
- validate_calculate_params params
14
- code = birthplace_part (params[:country_name] || Codes::ITALY), params[:city_name], params[:province_code]
15
- raise "Missing city/country code. Mispelled?" unless code
16
- code = surname_part(params[:surname]) + name_part(params[:name]) + birthdate_part(params[:birthdate], params[:gender]) + code
17
- code + check_character(code)
18
- end
19
-
20
- def validate_calculate_params params
21
- [:name, :surname, :gender, :birthdate].each do |param_name|
22
- raise "Missing #{param_name} parameter" unless params[param_name]
23
- end
24
- raise "Invalid birthdate: #{params[:birthdate]}" unless params[:birthdate].respond_to? :year
25
- unless Codes::GENDERS.include? params[:gender]
26
- raise "Invalid gender. Possible values are #{Codes::GENDERS}"
27
- end
28
- end
29
-
30
-
31
- # Methods to generate each part of the code
32
-
33
- def surname_part surname
34
- surname.upcase!
35
- code = first_three_consonants surname
36
- code << first_three_vowels(surname)
37
- truncate_and_right_pad_with_three_x code
38
- end
39
-
40
- def name_part name
41
- name.upcase!
42
- consonants_of_name = consonants name
43
- return consonants_of_name[0]+consonants_of_name[2..3] if consonants_of_name.size >= 4
44
- code = first_three_consonants name
45
- code << first_three_vowels(name)
46
- truncate_and_right_pad_with_three_x code
47
- end
48
-
49
- def birthdate_part birthdate, gender
50
- code = birthdate.year.to_s[2..3]
51
- code << Codes.month_letter(birthdate.month)
52
- day_part = gender.to_s.downcase[0] == 'f' ? birthdate.day + 40 : birthdate.day
53
- code << "#{day_part}".rjust(2, '0')
54
- end
55
-
56
- def city_code city_name, province_code
57
- return config.city_code.call(city_name, province_code) if config.city_code
58
- Codes.city city_name, province_code
59
- end
60
-
61
- def country_code country_name
62
- return config.country_code.call(country_name) if config.country_code
63
- Codes.country country_name
64
- end
65
-
66
- def birthplace_part country_name, city_name = nil, province_code = nil
67
- if Codes.italy? country_name
68
- city_code city_name, province_code
69
- else
70
- country_code country_name
71
- end
72
- end
73
-
74
- def check_character partial_fiscal_code
75
- numeric_value = 0
76
- partial_fiscal_code.split('').each_with_index do |chr, index|
77
- numeric_value += ((index+1) % 2 == 0) ? Codes.even_character(chr) : Codes.odd_character(chr)
78
- end
79
- Codes.check_character numeric_value % 26
80
- end
81
-
82
-
83
- # Helper methods
84
-
85
- # Intersect two strings or a string and an array of characters.
86
- def intersects string_a, string_or_array_b
87
- letters_a = string_a.split ''
88
- letters_b = string_or_array_b.respond_to?(:split) ? string_or_array_b.split('') : string_or_array_b
89
- selected_letters = letters_a.select { |letter| letters_b.include? letter }
90
- selected_letters.join ''
91
- end
92
-
93
- def consonants string
94
- intersects string, Alphabet.consonants
95
- end
96
-
97
- def first_three_consonants string
98
- intersects(string, Alphabet.consonants)[0..2]
99
- end
100
-
101
- def first_three_vowels string
102
- intersects(string, Alphabet.vowels)[0..2]
103
- end
104
-
105
- def truncate_and_right_pad_with_three_x string
106
- string[0..2].ljust 3, 'X'
16
+ def self.calculate params
17
+ citizen = ItalianCitizen.new params
18
+ raise ArgumentError.new("#{citizen.errors}") unless citizen.valid?
19
+ citizen.fiscal_code
107
20
  end
108
21
  end
@@ -1,5 +1,6 @@
1
1
  module CodiceFiscale
2
2
  module Codes
3
+ include Configurable
3
4
  extend self
4
5
 
5
6
  ITALY = 'Italia'
@@ -16,17 +17,14 @@ module CodiceFiscale
16
17
 
17
18
  GENDERS = [:male, :female]
18
19
 
19
- def config
20
- CodiceFiscale.config
21
- end
22
-
23
20
  def month_letter month_number
24
21
  month_number <= 0 ? nil : MONTH_CODES[month_number-1]
25
22
  end
26
23
 
27
24
  def city city_name, province_code
25
+ return config.city_code.call(city_name, province_code) if config.city_code
28
26
  CSV.foreach config.city_codes_csv_path do |row|
29
- if city_name.casecmp(row[3].strip) == 0 and province_code.casecmp(row[2].strip) == 0
27
+ if city_name.casecmp(row[3].strip).zero? and province_code.casecmp(row[2].strip).zero?
30
28
  return row[0].strip.upcase
31
29
  end
32
30
  end
@@ -34,8 +32,9 @@ module CodiceFiscale
34
32
  end
35
33
 
36
34
  def country country_name
35
+ return config.country_code.call(country_name) if config.country_code
37
36
  CSV.foreach config.country_codes_csv_path do |row|
38
- return row[3].strip.upcase if country_name.casecmp(row[2].strip) == 0
37
+ return row[3].strip.upcase if country_name.casecmp(row[2].strip).zero?
39
38
  end
40
39
  nil
41
40
  end
@@ -48,12 +47,12 @@ module CodiceFiscale
48
47
  EVEN_CODES[character.upcase]
49
48
  end
50
49
 
51
- def check_character number
50
+ def control_character number
52
51
  Alphabet.letters[number]
53
52
  end
54
53
 
55
54
  def italy? country_name
56
- ITALY.casecmp(country_name.strip) == 0
55
+ ITALY.casecmp(country_name.strip).zero?
57
56
  end
58
57
  end
59
58
  end
@@ -30,7 +30,18 @@ module CodiceFiscale
30
30
  end
31
31
 
32
32
 
33
- def config
33
+ module Configurable
34
+ def self.config
35
+ CodiceFiscale.config
36
+ end
37
+
38
+ def config
39
+ Configurable.config
40
+ end
41
+ end
42
+
43
+
44
+ def self.config
34
45
  @config ||= Configuration.new
35
46
  end
36
47
  end
@@ -0,0 +1,58 @@
1
+ module CodiceFiscale
2
+ class FiscalCode
3
+ include Helpers
4
+ include Configurable
5
+
6
+ attr_accessor :italian_citizen
7
+ alias :citizen :italian_citizen
8
+
9
+ delegate :name, :surname, :birthdate, :city_name, :province_code, :country_name, :to => :citizen
10
+
11
+ def initialize italian_citizen
12
+ @italian_citizen = italian_citizen
13
+ end
14
+
15
+ def calculate
16
+ code = surname_part + name_part + birthdate_part + birthplace_part
17
+ code + control_character(code)
18
+ end
19
+
20
+ def surname_part
21
+ first_three_consonants_than_vowels surname
22
+ end
23
+
24
+ def name_part
25
+ return "#{consonants_of_name[0]}#{consonants_of_name[2..3]}" if consonants_of_name.size >= 4
26
+ first_three_consonants_than_vowels name
27
+ end
28
+
29
+ def birthdate_part
30
+ code = birthdate.year.to_s[2..3]
31
+ code << Codes.month_letter(birthdate.month)
32
+ code << day_part
33
+ end
34
+
35
+ def day_part
36
+ number = citizen.female? ? birthdate.day + 40 : birthdate.day
37
+ "#{number}".rjust(2, '0')
38
+ end
39
+
40
+ def birthplace_part
41
+ code = citizen.born_in_italy? && Codes.city(city_name, province_code) || Codes.country(country_name)
42
+ raise "Cannot find a valid code for #{[country_name, city_name, province_code].compact.join ', '}" unless code
43
+ code
44
+ end
45
+
46
+ def control_character partial_fiscal_code
47
+ numeric_value = 0
48
+ partial_fiscal_code.split('').each_with_index do |chr, index|
49
+ numeric_value += (index+1).even? ? Codes.even_character(chr) : Codes.odd_character(chr)
50
+ end
51
+ Codes.control_character numeric_value % 26
52
+ end
53
+
54
+ def consonants_of_name
55
+ consonants name.upcase
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,33 @@
1
+ module CodiceFiscale
2
+ module Helpers
3
+ def intersection string_a, string_or_array_b
4
+ letters_a = string_a.split ''
5
+ letters_b = string_or_array_b.respond_to?(:split) ? string_or_array_b.split('') : string_or_array_b
6
+ selected_letters = letters_a.select { |letter| letters_b.include? letter }
7
+ selected_letters.join ''
8
+ end
9
+
10
+ def consonants string
11
+ intersection string, Alphabet.consonants
12
+ end
13
+
14
+ def first_three_consonants string
15
+ intersection(string, Alphabet.consonants)[0..2]
16
+ end
17
+
18
+ def first_three_vowels string
19
+ intersection(string, Alphabet.vowels)[0..2]
20
+ end
21
+
22
+ def truncate_and_right_pad_with_three_x string
23
+ string[0..2].ljust 3, 'X'
24
+ end
25
+
26
+ def first_three_consonants_than_vowels string
27
+ string.upcase!
28
+ code = first_three_consonants string
29
+ code << first_three_vowels(string)
30
+ truncate_and_right_pad_with_three_x code
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,48 @@
1
+ module CodiceFiscale
2
+ class ItalianCitizen
3
+ include ActiveModel::Validations
4
+
5
+ MANDATORY_ATTRIBUTES = [:name, :surname, :birthdate, :gender]
6
+
7
+ attr_accessor :city_name, :country_name, :province_code, *MANDATORY_ATTRIBUTES
8
+
9
+ # Validations
10
+
11
+ validates_presence_of *MANDATORY_ATTRIBUTES
12
+ validates_inclusion_of :gender, :in => [:male, :female]
13
+ validates_length_of :province_code, :is => 2, :allow_blank => true
14
+ validates_presence_of :city_name, :province_code, :if => lambda{ |obj| obj.born_in_italy? }
15
+ validate do
16
+ errors.add(:birthdate, :invalid) unless birthdate.respond_to? :year
17
+ end
18
+
19
+
20
+ # Instance methods
21
+
22
+ def initialize attributes
23
+ @attributes = default_attributes.merge attributes
24
+ @attributes.each { |name, value| send("#{name}=", value) }
25
+ end
26
+
27
+ def default_attributes
28
+ {:country_name => Codes::ITALY}
29
+ end
30
+
31
+ def born_in_italy?
32
+ Codes.italy? country_name
33
+ end
34
+
35
+ def female?
36
+ gender == :female
37
+ end
38
+
39
+ def fiscal_code
40
+ FiscalCode.new(self).calculate
41
+ end
42
+
43
+ # This method exists to support ActiveModel::Validations integration
44
+ def read_attribute_for_validation key
45
+ @attributes[key]
46
+ end
47
+ end
48
+ end
@@ -1,3 +1,3 @@
1
1
  module CodiceFiscale
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -0,0 +1,147 @@
1
+ require 'spec_helper'
2
+
3
+ describe CodiceFiscale::FiscalCode do
4
+ let(:citizen_marco_galli) { CodiceFiscale::ItalianCitizen.new :name => 'Marco', :surname => 'Galli', :gender => :male, :birthdate => Date.new(1983, 5, 3), :city_name => 'Oggiono', :province_code => 'LC' }
5
+ let(:fiscal_code) { described_class.new citizen_marco_galli }
6
+
7
+ describe '#surname_part' do
8
+ it 'takes the first 3 consonants' do
9
+ fiscal_code.surname_part.should == 'GLL'
10
+ end
11
+
12
+ it 'is 3 chrs long' do
13
+ fiscal_code.surname_part.size.should == 3
14
+ end
15
+
16
+ context 'when surname has only 1 consonant' do
17
+ before { fiscal_code.citizen.surname = 'oof' }
18
+
19
+ it 'puts the vowels after the consonants' do
20
+ fiscal_code.surname_part.should == 'FOO'
21
+ end
22
+ end
23
+
24
+ context 'when surname is less than 3 chrs long' do
25
+ before { fiscal_code.citizen.surname = 'm' }
26
+
27
+ it 'pads with the "X" character' do
28
+ fiscal_code.surname_part.should == 'MXX'
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '#name_part' do
34
+ it 'is 3 chrs long' do
35
+ fiscal_code.name_part.size.should == 3
36
+ end
37
+
38
+ context 'when name has 4 or more consonants' do
39
+ before { fiscal_code.citizen.name = 'danielino' }
40
+
41
+ it 'takes the 1st the 3rd and the 4th' do
42
+ fiscal_code.name_part.should == 'DLN'
43
+ end
44
+ end
45
+
46
+ context "when name has 3 or less consonants" do
47
+ before { fiscal_code.citizen.name = 'daniele' }
48
+
49
+ it 'takes the first 3 consonants' do
50
+ fiscal_code.name_part.should == 'DNL'
51
+ end
52
+ end
53
+
54
+ context 'when name has 2 consonants' do
55
+ before { fiscal_code.citizen.name = 'bar' }
56
+
57
+ it 'puts the vowels after the consonants' do
58
+ fiscal_code.name_part.should == 'BRA'
59
+ end
60
+ end
61
+
62
+ context 'name is less than 3 chrs long' do
63
+ before { fiscal_code.citizen.name = 'd' }
64
+
65
+ it 'pad with the "X" character' do
66
+ fiscal_code.name_part.should == 'DXX'
67
+ end
68
+ end
69
+ end
70
+
71
+
72
+ describe '#birthdate_part' do
73
+ it 'start with the last 2 digit of the year' do
74
+ fiscal_code.birthdate_part.should start_with '83'
75
+ end
76
+
77
+ describe 'the 3rd character' do
78
+ before { CodiceFiscale::Codes.stub(:month_letter).and_return('X') }
79
+
80
+ it 'is the month code' do
81
+ fiscal_code.birthdate_part[2].should == 'X'
82
+ end
83
+ end
84
+
85
+ describe 'the last 2 character' do
86
+ context 'gender is male' do
87
+ before { fiscal_code.citizen.gender = :male }
88
+
89
+ it('is the birth day') { fiscal_code.birthdate_part[3..5].should == '03' }
90
+ end
91
+
92
+ context 'gender is female' do
93
+ before { fiscal_code.citizen.gender = :female }
94
+
95
+ it('is the birth day + 40') { fiscal_code.birthdate_part[3..5].should == '43' }
96
+ end
97
+ end
98
+ end
99
+
100
+ describe '#birthplace_part' do
101
+ context 'when the country is Italy' do
102
+ before { fiscal_code.citizen.country_name = 'Italia' }
103
+
104
+ context 'when codes are fetched using a proc' do
105
+ before { fiscal_code.config.city_code { 'Winterfell' } }
106
+
107
+ it 'returns the result of the city-block execution' do
108
+ fiscal_code.birthplace_part.should == 'Winterfell'
109
+ end
110
+ end
111
+
112
+ context 'when codes are fetched using csv' do
113
+ before { CodiceFiscale::Codes.stub!(:city).and_return('hello') }
114
+
115
+ it 'returns the city code' do
116
+ fiscal_code.birthplace_part.should == 'hello'
117
+ end
118
+ end
119
+ end
120
+
121
+ context 'when the country is not Italy' do
122
+ before { fiscal_code.citizen.country_name = 'Francia' }
123
+
124
+ context 'when codes are fetched using a proc' do
125
+ before { fiscal_code.config.country_code { 'The North' } }
126
+
127
+ it 'returns the result of the country-block execution' do
128
+ fiscal_code.birthplace_part.should == 'The North'
129
+ end
130
+ end
131
+
132
+ context 'when codes are fetched using csv' do
133
+ before { CodiceFiscale::Codes.stub!(:country).and_return('Middle-Earth') }
134
+
135
+ it 'returns the country code' do
136
+ fiscal_code.birthplace_part.should == 'Middle-Earth'
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ describe '#control_character' do
143
+ it 'returns the expected letter' do
144
+ fiscal_code.control_character('RSSMRA87A01A005').should == 'V'
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ #TODO
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe CodiceFiscale::ItalianCitizen do
4
+ let(:marco_attributes) { {:name => 'Marco', :surname => 'Galli', :gender => :male, :birthdate => Date.new(1983, 5, 2), :city_name => 'Oggiono', :province_code => 'LC'} }
5
+ let(:john_attributes) { {:name => 'John', :surname => 'Snow', :gender => :male, :birthdate => Date.new(1971, 9, 12), :country_name => 'Canada'} }
6
+ let(:marco) { described_class.new marco_attributes }
7
+ let(:john) { described_class.new john_attributes }
8
+
9
+
10
+ describe '#initialize' do
11
+ it 'accepts 1 attribute' do
12
+ lambda { marco }.should_not raise_error
13
+ end
14
+
15
+ it 'do not accepts 0 attribute' do
16
+ lambda { described_class.new }.should raise_error(ArgumentError)
17
+ end
18
+ end
19
+
20
+
21
+ describe '#validations' do
22
+ describe 'when all attributes are valid' do
23
+ it 'is valid' do
24
+ marco.should be_valid
25
+ john.should be_valid
26
+ end
27
+ end
28
+
29
+ describe 'when name is not present' do
30
+ let(:citizen_without_name) { described_class.new marco_attributes.reject {|n| n == :name } }
31
+
32
+ it 'is not valid' do
33
+ citizen_without_name.valid?
34
+ citizen_without_name.errors[:name].should_not be_empty
35
+ end
36
+ end
37
+
38
+ describe 'when gender is not valid' do
39
+ let(:citizen_with_strange_gender) { described_class.new marco_attributes.merge(:gender => :strange) }
40
+
41
+ it 'is not valid' do
42
+ citizen_with_strange_gender.valid?
43
+ citizen_with_strange_gender.errors[:gender].should_not be_empty
44
+ end
45
+ end
46
+
47
+ describe 'when the province code is not 2 characters long' do
48
+ let(:citizen_with_invalid_province) { described_class.new marco_attributes.merge(:province_code => 'LECCO') }
49
+
50
+ it 'is not valid' do
51
+ citizen_with_invalid_province.valid?
52
+ citizen_with_invalid_province.errors[:province_code].should_not be_empty
53
+ end
54
+ end
55
+
56
+ describe 'when the bitrhdate is not valid' do
57
+ let(:citizen_with_invalid_date) { described_class.new marco_attributes.merge(:birthdate => 'xxx') }
58
+
59
+ it 'is not valid' do
60
+ citizen_with_invalid_date.valid?
61
+ citizen_with_invalid_date.errors[:birthdate].should_not be_empty
62
+ end
63
+ end
64
+ end
65
+ end
@@ -1,214 +1,24 @@
1
1
  require 'spec_helper'
2
2
 
3
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
-
4
+ describe '#calculate' do
5
+ let(:mario_attributes) { {:name => 'mario', :surname => 'rossi', :gender => :male, :birthdate => Date.new(1987, 1, 1),
6
+ :province_code => 'lc', :city_name => 'Abbadia Lariana'} }
131
7
 
132
- describe '#birthplace_part' do
133
8
  before do
134
- subject.config.country_code = nil
135
9
  subject.config.city_code = nil
10
+ subject.config.country_code = nil
136
11
  end
137
12
 
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 = {:name => 'mario', :surname => 'rossi', :gender => :male, :birthdate => Date.new(1987, 1, 1),
172
- :province_code => 'lc', :city_name => 'Abbadia Lariana'}
173
- subject.calculate(params).should == 'RSSMRA87A01A005V'
174
- end
175
- end
176
-
177
- context 'return the expected code' do
178
- it 'work' do
179
- params = {:name => 'mario', :surname => 'rossi', :gender => :male, :birthdate => Date.new(1987, 1, 1), :country_name => 'Albania'}
180
- subject.calculate(params).should == 'RSSMRA87A01Z100H'
181
- end
182
- end
183
- end
184
-
185
- describe '#validate_calculate_params' do
186
- let(:mandatory_params) { {:name => 'mario', :surname => 'rossi', :gender => :male, :birthdate => Date.new(1987, 1, 1)} }
187
-
188
- context 'All mandatory params are correct' do
189
- it 'do not raise any arror' do
190
- lambda { subject.validate_calculate_params(mandatory_params) }.should_not raise_error
191
- end
192
- end
193
-
194
- context 'A mandatory parameter is missing' do
195
- it 'raise an error' do
196
- without_name = mandatory_params.reject {|p| p == :name }
197
- lambda { subject.validate_calculate_params(without_name) }.should raise_error
198
- end
13
+ it 'returns the expected code' do
14
+ subject.calculate(mario_attributes).should == 'RSSMRA87A01A005V'
199
15
  end
200
16
 
201
- context 'Gender is invalid' do
202
- it 'raise an error' do
203
- params = mandatory_params.merge :gender => :lol
204
- lambda { subject.validate_calculate_params(params) }.should raise_error
205
- end
206
- end
17
+ context 'when params are not valid' do
18
+ let(:invalid_attributes) { mario_attributes.merge(:name => '') }
207
19
 
208
- context 'Birthdate is invalid' do
209
- it 'raise an error' do
210
- params = mandatory_params.merge :birthdate => '2000/01/01'
211
- lambda { subject.validate_calculate_params(params) }.should raise_error
20
+ it 'raises an error' do
21
+ lambda { subject.calculate(invalid_attributes) }.should raise_error(ArgumentError)
212
22
  end
213
23
  end
214
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codice-fiscale
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-05 00:00:00.000000000 Z
12
+ date: 2012-12-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -75,6 +75,38 @@ dependencies:
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: active_support
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: activemodel
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
78
110
  description: Calculate the italian fiscal code
79
111
  email:
80
112
  - dani.m.mobile@gmail.com
@@ -95,11 +127,17 @@ files:
95
127
  - lib/codice_fiscale/codes/city_codes.csv
96
128
  - lib/codice_fiscale/codes/country_codes.csv
97
129
  - lib/codice_fiscale/configuration.rb
130
+ - lib/codice_fiscale/fiscal_code.rb
131
+ - lib/codice_fiscale/helpers.rb
132
+ - lib/codice_fiscale/italian_citizen.rb
98
133
  - lib/codice_fiscale/version.rb
99
134
  - spec/fixtures/city_codes.csv
100
135
  - spec/fixtures/country_codes.csv
101
136
  - spec/lib/codice_fiscale/alphabet_spec.rb
102
137
  - spec/lib/codice_fiscale/codes_spec.rb
138
+ - spec/lib/codice_fiscale/fiscal_code_spec.rb
139
+ - spec/lib/codice_fiscale/helpers_spec.rb
140
+ - spec/lib/codice_fiscale/italian_citizen_spec.rb
103
141
  - spec/lib/codice_fiscale_spec.rb
104
142
  - spec/spec_helper.rb
105
143
  homepage: https://github.com/daniele-m/codice_fiscale
@@ -131,5 +169,8 @@ test_files:
131
169
  - spec/fixtures/country_codes.csv
132
170
  - spec/lib/codice_fiscale/alphabet_spec.rb
133
171
  - spec/lib/codice_fiscale/codes_spec.rb
172
+ - spec/lib/codice_fiscale/fiscal_code_spec.rb
173
+ - spec/lib/codice_fiscale/helpers_spec.rb
174
+ - spec/lib/codice_fiscale/italian_citizen_spec.rb
134
175
  - spec/lib/codice_fiscale_spec.rb
135
176
  - spec/spec_helper.rb