codice-fiscale 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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