company_number 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +4 -0
- data/.github/workflows/ci.yml +76 -0
- data/.rubocop.yml +20 -7
- data/.simplecov +6 -0
- data/CHANGELOG.md +17 -2
- data/CODE_OF_CONDUCT.md +2 -2
- data/Gemfile +3 -1
- data/README.md +102 -12
- data/Rakefile +5 -5
- data/bin/setup +1 -1
- data/company_number.gemspec +8 -8
- data/config/dictionary.yml +3 -3
- data/lib/company_number/configuration.rb +43 -0
- data/lib/company_number/dictionary.rb +51 -0
- data/lib/company_number/number.rb +22 -15
- data/lib/company_number/validation.rb +60 -0
- data/lib/company_number/version.rb +1 -1
- data/lib/company_number.rb +25 -5
- data/rubocop/rubocop.html +433 -0
- metadata +26 -34
- data/.github/workflows/build.yml +0 -93
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c02ace863de99e8b6d41ff12185285c5c4bff2131e45d23873981cf0115e03ee
|
4
|
+
data.tar.gz: 81ab67bc56f3de3edf78432cdb679ede3237d7fdcb40266f666ed6713c3dde35
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b6ff3493c540f62461a948d05de2ee4206ee0c2851d366eaf46e632802f74d7c9fc21c1a232404eef724197e70ee1194ec99ec3dea3c2363c53879352736799
|
7
|
+
data.tar.gz: 8973da310ae9ba856ca2553c3d1e8c27fdd3f0a20ff03044b1487539a735f6548ee9b8f51974fc4635421297fcb95320ab1a9cc1bc2be6939a4aa354d7c7b94f
|
data/.codeclimate.yml
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
name: "CI"
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- "*"
|
7
|
+
pull_request:
|
8
|
+
branches:
|
9
|
+
- "*"
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
lint:
|
13
|
+
name: "RuboCop"
|
14
|
+
timeout-minutes: 5
|
15
|
+
runs-on: "ubuntu-latest"
|
16
|
+
steps:
|
17
|
+
- uses: "actions/checkout@v3"
|
18
|
+
|
19
|
+
- name: "Set up Ruby"
|
20
|
+
uses: "ruby/setup-ruby@v1"
|
21
|
+
with:
|
22
|
+
ruby-version: "3.1"
|
23
|
+
bundler-cache: true
|
24
|
+
|
25
|
+
- name: "Run RuboCop"
|
26
|
+
run: "bundle exec rubocop"
|
27
|
+
|
28
|
+
test:
|
29
|
+
runs-on: "ubuntu-latest"
|
30
|
+
strategy:
|
31
|
+
fail-fast: false
|
32
|
+
matrix:
|
33
|
+
ruby-version:
|
34
|
+
- "2.5"
|
35
|
+
- "2.6"
|
36
|
+
- "2.7"
|
37
|
+
- "3.0"
|
38
|
+
- "3.1"
|
39
|
+
|
40
|
+
steps:
|
41
|
+
- uses: "actions/checkout@v3"
|
42
|
+
|
43
|
+
- name: "Set up Ruby"
|
44
|
+
uses: "ruby/setup-ruby@v1"
|
45
|
+
with:
|
46
|
+
ruby-version: "${{ matrix.ruby-version }}"
|
47
|
+
bundler-cache: true
|
48
|
+
|
49
|
+
- name: "Run specs"
|
50
|
+
run: "bundle exec rspec"
|
51
|
+
|
52
|
+
- name: "Upload artifacts"
|
53
|
+
uses: "actions/upload-artifact@v3"
|
54
|
+
with:
|
55
|
+
name: "coverage-artifacts"
|
56
|
+
path: "${{github.workspace}}/coverage/coverage.json"
|
57
|
+
retention-days: 1
|
58
|
+
|
59
|
+
coverage:
|
60
|
+
name: "Report coverage to Code Climate"
|
61
|
+
runs-on: "ubuntu-20.04"
|
62
|
+
needs: "test"
|
63
|
+
if: "success() && github.ref == 'refs/heads/master'"
|
64
|
+
env:
|
65
|
+
CC_TEST_REPORTER_ID: "${{ secrets.CC_TEST_REPORTER_ID }}"
|
66
|
+
|
67
|
+
steps:
|
68
|
+
- uses: "actions/checkout@v3"
|
69
|
+
|
70
|
+
- name: "Download coverage artifacts from test job"
|
71
|
+
uses: "actions/download-artifact@v3"
|
72
|
+
with:
|
73
|
+
name: "coverage-artifacts"
|
74
|
+
- uses: "paambaati/codeclimate-action@v3.2.0"
|
75
|
+
with:
|
76
|
+
coverageLocations: "coverage.json:simplecov"
|
data/.rubocop.yml
CHANGED
@@ -1,15 +1,18 @@
|
|
1
1
|
AllCops:
|
2
|
-
TargetRubyVersion: 2.
|
2
|
+
TargetRubyVersion: 2.5
|
3
|
+
NewCops: enable
|
4
|
+
SuggestExtensions: false
|
5
|
+
Exclude:
|
6
|
+
- "vendor/**/*"
|
3
7
|
|
4
8
|
Style/FrozenStringLiteralComment:
|
5
9
|
Enabled: false
|
6
10
|
|
7
11
|
Style/StringLiterals:
|
8
|
-
|
12
|
+
EnforcedStyle: double_quotes
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
- spec/**/*
|
14
|
+
Style/Documentation:
|
15
|
+
Enabled: false
|
13
16
|
|
14
17
|
Metrics/CyclomaticComplexity:
|
15
18
|
Enabled: true
|
@@ -17,8 +20,18 @@ Metrics/CyclomaticComplexity:
|
|
17
20
|
Metrics/MethodLength:
|
18
21
|
Max: 20
|
19
22
|
|
23
|
+
Metrics/BlockLength:
|
24
|
+
Exclude:
|
25
|
+
- "spec/**/*_spec.rb"
|
26
|
+
- "*.gemspec"
|
27
|
+
|
20
28
|
Layout/LineLength:
|
21
|
-
|
29
|
+
Exclude:
|
30
|
+
- "spec/**/*_spec.rb"
|
31
|
+
- "*.gemspec"
|
22
32
|
|
23
33
|
Naming/MemoizedInstanceVariableName:
|
24
|
-
|
34
|
+
EnforcedStyleForLeadingUnderscores: optional
|
35
|
+
|
36
|
+
Gemspec/RequireMFA:
|
37
|
+
Enabled: false
|
data/.simplecov
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,12 +1,27 @@
|
|
1
1
|
## Changelog
|
2
2
|
|
3
|
+
### 0.1.3 - 2022-11-04
|
4
|
+
* Enhancements:
|
5
|
+
* Update CI - f67a9e3
|
6
|
+
* Update RuboCop configuration - 3af3dc7
|
7
|
+
|
8
|
+
### 0.1.2 - 2022-04-21
|
9
|
+
* Features:
|
10
|
+
* Add custom configurations - aae0d51
|
11
|
+
- custom_dictionary
|
12
|
+
- strict_validation
|
13
|
+
- excluded_countries
|
14
|
+
|
15
|
+
* Enhancements:
|
16
|
+
* Update RuboCop configuration - dcd9852
|
17
|
+
|
3
18
|
### 0.1.1 - 2022-04-04
|
4
19
|
* Features:
|
5
20
|
* Add dictionary to return the company number metadata - b19c8d9
|
6
21
|
|
7
22
|
* Deprecations:
|
8
|
-
* Remove `regexp` attr_reader (moved to metadata)
|
9
|
-
* Remove `countries` attr_reader to use `CompanyNumber::Number#valid_countries`
|
23
|
+
* Remove `regexp` attr_reader (moved to metadata)
|
24
|
+
* Remove `countries` attr_reader to use `CompanyNumber::Number#valid_countries`
|
10
25
|
|
11
26
|
* Bug fixes:
|
12
27
|
* Fix `CompanyNumber::Number#to_s` method not to return trailing whitespace when country code is not filled in - 9b4f3c53
|
data/CODE_OF_CONDUCT.md
CHANGED
@@ -22,7 +22,7 @@ Examples of unacceptable behavior include:
|
|
22
22
|
advances of any kind
|
23
23
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
24
24
|
* Public or private harassment
|
25
|
-
* Publishing others
|
25
|
+
* Publishing others" private information, such as a physical or email
|
26
26
|
address, without their explicit permission
|
27
27
|
* Other conduct which could reasonably be considered inappropriate in a
|
28
28
|
professional setting
|
@@ -76,7 +76,7 @@ Community leaders will follow these Community Impact Guidelines in determining t
|
|
76
76
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
|
77
77
|
available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
78
78
|
|
79
|
-
Community Impact Guidelines were inspired by [Mozilla
|
79
|
+
Community Impact Guidelines were inspired by [Mozilla"s code of conduct enforcement ladder](https://github.com/mozilla/diversity).
|
80
80
|
|
81
81
|
[homepage]: https://www.contributor-covenant.org
|
82
82
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
# CompanyNumber
|
2
2
|
|
3
|
-
[![
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/company_number.svg)](https://badge.fury.io/rb/company_number)
|
4
|
+
[![Build Status](https://github.com/VictorAuthiat/company_number/actions/workflows/ci.yml/badge.svg)](https://github.com/VictorAuthiat/company_number/actions/workflows/ci.yml)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/VictorAuthiat/company_number/badges/gpa.svg)](https://codeclimate.com/github/VictorAuthiat/company_number)
|
6
|
+
[![Test Coverage](https://codeclimate.com/github/VictorAuthiat/company_number/badges/coverage.svg)](https://codeclimate.com/github/VictorAuthiat/company_number/coverage)
|
7
|
+
[![Issue Count](https://codeclimate.com/github/VictorAuthiat/company_number/badges/issue_count.svg)](https://codeclimate.com/github/VictorAuthiat/company_number)
|
4
8
|
|
5
9
|
CompanyNumber is a gem allowing you to validate company number based on a country code
|
6
10
|
|
7
11
|
## Installation
|
8
12
|
|
9
|
-
Add this line to your application
|
13
|
+
Add this line to your application"s Gemfile:
|
10
14
|
|
11
15
|
```ruby
|
12
|
-
gem
|
16
|
+
gem "company_number"
|
13
17
|
```
|
14
18
|
|
15
19
|
And then execute:
|
@@ -25,7 +29,7 @@ Or install it yourself as:
|
|
25
29
|
You can obtain a `CompanyNumber::Number` object calling `parse` method:
|
26
30
|
|
27
31
|
```ruby
|
28
|
-
company_number = CompanyNumber.parse(
|
32
|
+
company_number = CompanyNumber.parse("123456789", :fr)
|
29
33
|
|
30
34
|
# => #<CompanyNumber::Number:0x00007fc015d04e18 @company_number="123456789", @country_code=:fr, @metadata={:country=>"France", :name=>"Numéro SIREN ou SIRET", :regexp=>"^(\\d{9}|\\d{14})$", :pattern=>"9 numbers (XXXXXXXXX) or 14 numbers (XXXXXXXXXXXXXX)"}>
|
31
35
|
```
|
@@ -33,12 +37,9 @@ company_number = CompanyNumber.parse('123456789', :fr)
|
|
33
37
|
Then you can run validation methods
|
34
38
|
|
35
39
|
```ruby
|
36
|
-
company_number.valid?
|
37
|
-
# => true
|
38
|
-
company_number.
|
39
|
-
# => true
|
40
|
-
company_number.valid_for_country?(:at)
|
41
|
-
# => false
|
40
|
+
company_number.valid? # => true
|
41
|
+
company_number.valid_country? # => true
|
42
|
+
company_number.valid_for_country?(:at) # => false
|
42
43
|
```
|
43
44
|
|
44
45
|
You can also fetch valid countries
|
@@ -72,7 +73,7 @@ company_number.to_h
|
|
72
73
|
You can compare 2 instances of `CompanyNumber::Number` with `==` method
|
73
74
|
|
74
75
|
```ruby
|
75
|
-
CompanyNumber.parse(
|
76
|
+
CompanyNumber.parse("123") == CompanyNumber.parse("123")
|
76
77
|
# => true
|
77
78
|
```
|
78
79
|
|
@@ -82,6 +83,95 @@ CompanyNumber.dictionary
|
|
82
83
|
# => {:at=>{:country=>"Austria", :name=>"Firmenbuchnummer", :regexp=>"^([a-zA-Z]{2}\\d{1,6}|\\d{1,6})[A-Z]$", :pattern=>"2 letters + 6 numbers + 1 letter (LLXXXXXXL)", :variations=>"1-6 numbers + 1 letter (XXXXXXL)"}, ...}
|
83
84
|
```
|
84
85
|
|
86
|
+
## Configuration
|
87
|
+
You can configure your own dictionary using **custom_dictionary**.
|
88
|
+
It should be a hash with the country codes as keys and the associated metadata as values.
|
89
|
+
|
90
|
+
Available metadata keys:
|
91
|
+
- country
|
92
|
+
- name
|
93
|
+
- regexp
|
94
|
+
- pattern
|
95
|
+
- variations
|
96
|
+
|
97
|
+
**Example:**
|
98
|
+
```ruby
|
99
|
+
CompanyNumber.parse("123456789", :fr).valid? # => true
|
100
|
+
CompanyNumber.parse("12345678901234", :fr).valid? # => true
|
101
|
+
|
102
|
+
CompanyNumber.configure do |config|
|
103
|
+
config.custom_dictionary = { fr: { regexp: "^\d{14}$" } }
|
104
|
+
end
|
105
|
+
|
106
|
+
CompanyNumber.parse("123456789", :fr).valid? # => false
|
107
|
+
CompanyNumber.parse("12345678901234", :fr).valid? # => true
|
108
|
+
```
|
109
|
+
|
110
|
+
**strict_validation:**
|
111
|
+
|
112
|
+
You can also enable strict validation to reject unknow countries:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
CompanyNumber.parse("123456789").valid? # => true
|
116
|
+
CompanyNumber.parse("123456789", :tt).valid? # => true
|
117
|
+
|
118
|
+
CompanyNumber.configure do |config|
|
119
|
+
config.strict_validation = true
|
120
|
+
end
|
121
|
+
|
122
|
+
CompanyNumber.parse("123456789").valid? # => false
|
123
|
+
CompanyNumber.parse("123456789", :tt).valid? # => false
|
124
|
+
```
|
125
|
+
|
126
|
+
**excluded_countries:**
|
127
|
+
|
128
|
+
You may want to exclude some countries, this allows you to automatically validate the country"s company number when strict validation is not enabled. You can also exclude a country to overwrite all its metadata and define it later in a custom dictionary.
|
129
|
+
|
130
|
+
**Example:**
|
131
|
+
```ruby
|
132
|
+
CompanyNumber.parse("123456789", :be).valid? # => false
|
133
|
+
|
134
|
+
CompanyNumber.configure do |config|
|
135
|
+
config.excluded_countries = [:be]
|
136
|
+
end
|
137
|
+
|
138
|
+
CompanyNumber.parse("123456789", :be).valid? # => true
|
139
|
+
```
|
140
|
+
|
141
|
+
## Default dictionary:
|
142
|
+
|
143
|
+
- `:at` - **Austria** - Firmenbuchnummer
|
144
|
+
- `:be` - **Belgium** - Numéro d"entreprise Vestigingseenheidsnummer
|
145
|
+
- `:bg` - **Bulgaria** - ЕИК (EIK)/ПИК (PIK) (UIC/PIC)
|
146
|
+
- `:hr` - **Croatia** - Matični broj poslovnog subjekta (MBS)
|
147
|
+
- `:cy` - **Cyprus** - Αριθμός Μητρώου Εταιρίας Şirket kayıt numarası
|
148
|
+
- `:cz` - **Czech** - epublic (Identifikační číslo
|
149
|
+
- `:dk` - **Denmark** - CVR-nummer
|
150
|
+
- `:ee` - **Estonia** - Kood
|
151
|
+
- `:fi` - **Finland** - Y-tunnus FO-nummer
|
152
|
+
- `:fr` - **France** - Numéro SIREN ou SIRET
|
153
|
+
- `:de` - **Germany** - Nummer der Firma Registernummer
|
154
|
+
- `:gr` - **Greece** - Αριθμό Φορολογικού Μητρώου (Α.Φ.Μ.)
|
155
|
+
- `:hu` - **Hungary** - Cégjegyzékszáma
|
156
|
+
- `:ie` - **Ireland** - Company Number
|
157
|
+
- `:is` - **Island** - TIN
|
158
|
+
- `:it` - **Italy** - Codice fiscale
|
159
|
+
- `:lv` - **Latvia** - Reģistrācijas numurs
|
160
|
+
- `:li` - **Liechtenstein** - UID
|
161
|
+
- `:lt` - **Lithuania** - Juridinio asmens kodas
|
162
|
+
- `:lu` - **Luxembourg** - Numéro d"immatriculation
|
163
|
+
- `:mt` - **Malta** - Registration Number
|
164
|
+
- `:nl` - **Netherlands** - KvK-nummer
|
165
|
+
- `:no` - **Norway** - TIN
|
166
|
+
- `:pl` - **Poland** - Numer w Krajowym Rejestrze Sądowym (numer KRS)) NIPC)
|
167
|
+
- `:ro` - **Romania** - Număr de ordine în Registrul Comerţului
|
168
|
+
- `:sk` - **Slovakia** - Identifikačného čísla Identification number
|
169
|
+
- `:si` - **Slovenia** - Matična številka
|
170
|
+
- `:es` - **Spain** - Número de identificación fiscal (NIF)
|
171
|
+
- `:se` - **Sweden** - Registreringsnummer
|
172
|
+
- `:ch` - **Switzerland** - UID
|
173
|
+
- `:gb` - **United Kingdom** - Company Number Registration Number
|
174
|
+
|
85
175
|
## Development
|
86
176
|
|
87
177
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -98,4 +188,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
98
188
|
|
99
189
|
## Code of Conduct
|
100
190
|
|
101
|
-
Everyone interacting in the CompanyNumber project
|
191
|
+
Everyone interacting in the CompanyNumber project"s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/victorauthiat/company_number/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "bundler/setup"
|
3
4
|
require "bundler/gem_tasks"
|
4
|
-
require "rspec/core/rake_task"
|
5
|
-
|
6
|
-
RSpec::Core::RakeTask.new(:spec)
|
7
5
|
|
6
|
+
require "rspec/core/rake_task"
|
8
7
|
require "rubocop/rake_task"
|
9
8
|
|
10
|
-
|
9
|
+
RSpec::Core::RakeTask.new(:test)
|
10
|
+
RuboCop::RakeTask.new(:rubocop)
|
11
11
|
|
12
|
-
task default: %i[
|
12
|
+
task default: %i[rubocop test]
|
data/bin/setup
CHANGED
data/company_number.gemspec
CHANGED
@@ -8,9 +8,10 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.authors = ["victorauthiat"]
|
9
9
|
spec.email = ["authiatv@gmail.com"]
|
10
10
|
|
11
|
-
spec.summary =
|
12
|
-
spec.homepage =
|
13
|
-
spec.license =
|
11
|
+
spec.summary = "Validate a company number according to a country code"
|
12
|
+
spec.homepage = "https://github.com/victorauthiat/company_number"
|
13
|
+
spec.license = "MIT"
|
14
|
+
spec.required_ruby_version = ">= 2.5"
|
14
15
|
|
15
16
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
16
17
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
@@ -19,9 +20,8 @@ Gem::Specification.new do |spec|
|
|
19
20
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
20
21
|
spec.require_paths = ["lib"]
|
21
22
|
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency 'simplecov', '~> 0.21.2'
|
23
|
+
spec.add_development_dependency "bundler"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_development_dependency "simplecov"
|
27
27
|
end
|
data/config/dictionary.yml
CHANGED
@@ -7,7 +7,7 @@ at:
|
|
7
7
|
|
8
8
|
be:
|
9
9
|
country: Belgium
|
10
|
-
name: Numéro d
|
10
|
+
name: Numéro d"entreprise Vestigingseenheidsnummer
|
11
11
|
regexp: ^\d{10}$
|
12
12
|
pattern: 10 numbers (XXXXXXXXXX)
|
13
13
|
|
@@ -124,9 +124,9 @@ lt:
|
|
124
124
|
|
125
125
|
lu:
|
126
126
|
country: Luxembourg
|
127
|
-
name: Numéro d
|
127
|
+
name: Numéro d"immatriculation
|
128
128
|
regexp: ^[a-zA-Z]{1}\d{6}|[a-jA-J]\d{3}$
|
129
|
-
pattern: 1 letter + 6 numbers (LXXXXXX)
|
129
|
+
pattern: 1 letter + 6 numbers (LXXXXXX)"
|
130
130
|
variations: 1 letter (from A to J) + 3 numbers (AXXX)
|
131
131
|
|
132
132
|
mt:
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CompanyNumber
|
4
|
+
class Configuration
|
5
|
+
attr_reader :excluded_countries,
|
6
|
+
:custom_dictionary,
|
7
|
+
:strict_validation
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@excluded_countries = []
|
11
|
+
@custom_dictionary = {}
|
12
|
+
@strict_validation = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def dictionary
|
16
|
+
@dictionary ||= CompanyNumber::Dictionary.new(@custom_dictionary)
|
17
|
+
end
|
18
|
+
|
19
|
+
def strict_validation?
|
20
|
+
!!@strict_validation
|
21
|
+
end
|
22
|
+
|
23
|
+
def custom_dictionary=(value)
|
24
|
+
Validation.check_dictionary_structure(value)
|
25
|
+
|
26
|
+
@dictionary = nil
|
27
|
+
@custom_dictionary = value
|
28
|
+
end
|
29
|
+
|
30
|
+
def excluded_countries=(value)
|
31
|
+
Validation.check_object_class(value, [Array])
|
32
|
+
|
33
|
+
@dictionary = nil
|
34
|
+
@excluded_countries = value
|
35
|
+
end
|
36
|
+
|
37
|
+
def strict_validation=(value)
|
38
|
+
Validation.check_object_class(value, [TrueClass, FalseClass, NilClass])
|
39
|
+
|
40
|
+
@strict_validation = value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CompanyNumber
|
4
|
+
class Dictionary
|
5
|
+
attr_reader :country_codes_metadata, :default_hash
|
6
|
+
|
7
|
+
def self.default_dictionary_path
|
8
|
+
File.join(File.dirname(__FILE__), "../../config/dictionary.yml")
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(country_codes_metadata = {})
|
12
|
+
@country_codes_metadata = country_codes_metadata
|
13
|
+
@default_hash = load_default_hash
|
14
|
+
|
15
|
+
validate_country_codes_metadata
|
16
|
+
end
|
17
|
+
|
18
|
+
def values
|
19
|
+
@_values ||= fetch_values
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def fetch_values
|
25
|
+
transformed_hash =
|
26
|
+
@default_hash.merge(@country_codes_metadata) do |country_code, _, value|
|
27
|
+
@default_hash[country_code.downcase].merge(value)
|
28
|
+
end
|
29
|
+
|
30
|
+
transformed_hash.reject do |country_code, _metadata|
|
31
|
+
CompanyNumber.configuration.excluded_countries.include?(country_code)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def load_default_hash
|
36
|
+
YAML.safe_load(
|
37
|
+
File.read(self.class.default_dictionary_path),
|
38
|
+
symbolize_names: true
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate_country_codes_metadata
|
43
|
+
Validation.check_object_class(@country_codes_metadata, [Hash])
|
44
|
+
|
45
|
+
@country_codes_metadata.each do |country_code, metadata|
|
46
|
+
Validation.check_string_format(country_code, /^[A-Za-z]{2}$/)
|
47
|
+
Validation.check_country_code_metadata(metadata)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,10 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module CompanyNumber
|
2
4
|
class Number
|
3
5
|
attr_reader :company_number, :country_code, :metadata
|
4
6
|
|
5
7
|
def initialize(company_number, country_code = nil)
|
6
|
-
|
7
|
-
|
8
|
+
Validation.check_object_class(company_number, [String])
|
9
|
+
Validation.check_object_class(country_code, [NilClass, Symbol, String])
|
10
|
+
Validation.check_iso_code_format(country_code)
|
8
11
|
|
9
12
|
@company_number = company_number
|
10
13
|
@country_code = country_code&.downcase&.to_sym
|
@@ -28,17 +31,22 @@ module CompanyNumber
|
|
28
31
|
end
|
29
32
|
|
30
33
|
def valid?
|
31
|
-
|
34
|
+
if CompanyNumber.strict_validation?
|
35
|
+
country_code_present_and_valid_country?
|
36
|
+
else
|
37
|
+
no_country_code_or_valid_country?
|
38
|
+
end
|
32
39
|
end
|
33
40
|
|
34
41
|
def valid_country?
|
35
|
-
CompanyNumber.dictionary.keys.include?(@country_code)
|
42
|
+
CompanyNumber.dictionary.keys.include?(@country_code) ||
|
43
|
+
(!CompanyNumber.strict_validation? && !!@country_code)
|
36
44
|
end
|
37
45
|
|
38
46
|
def valid_for_country?(country_code)
|
39
|
-
|
40
|
-
|
41
|
-
|
47
|
+
Validation.check_iso_code_format(country_code)
|
48
|
+
regexp = CompanyNumber.dictionary.dig(country_code, :regexp)
|
49
|
+
(!CompanyNumber.strict_validation? && !regexp) || valid_code?(regexp)
|
42
50
|
end
|
43
51
|
|
44
52
|
def valid_countries
|
@@ -52,17 +60,16 @@ module CompanyNumber
|
|
52
60
|
|
53
61
|
private
|
54
62
|
|
55
|
-
def
|
56
|
-
|
57
|
-
|
58
|
-
Regexp.new(regexp) unless regexp.nil?
|
63
|
+
def no_country_code_or_valid_country?
|
64
|
+
!@country_code || valid_for_country?(@country_code)
|
59
65
|
end
|
60
66
|
|
61
|
-
def
|
62
|
-
|
67
|
+
def country_code_present_and_valid_country?
|
68
|
+
!!@country_code && valid_for_country?(@country_code)
|
69
|
+
end
|
63
70
|
|
64
|
-
|
65
|
-
|
71
|
+
def valid_code?(regexp = nil)
|
72
|
+
!!regexp && !!(@company_number =~ Regexp.new(regexp))
|
66
73
|
end
|
67
74
|
end
|
68
75
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CompanyNumber
|
4
|
+
module Validation
|
5
|
+
ISO_CODE_REGEXP = /^[A-Za-z]{2}$/.freeze
|
6
|
+
|
7
|
+
AVAILABLE_METADATA_KEYS = %i[
|
8
|
+
variations
|
9
|
+
pattern
|
10
|
+
country
|
11
|
+
regexp
|
12
|
+
name
|
13
|
+
].freeze
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def check_object_class(object, expected_classes = [])
|
17
|
+
return if expected_classes.include?(object.class)
|
18
|
+
|
19
|
+
raise ArgumentError,
|
20
|
+
"Expect #{object} class to be #{expected_classes.join(', ')}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_object_inclusion(object, expected_objects = [])
|
24
|
+
return if expected_objects.include?(object)
|
25
|
+
|
26
|
+
raise ArgumentError,
|
27
|
+
"Expect #{object} to be part of #{expected_objects}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def check_string_format(string, regexp)
|
31
|
+
return if string =~ regexp
|
32
|
+
|
33
|
+
raise ArgumentError, "Expect #{string} to match regexp: #{regexp}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def check_iso_code_format(country_code)
|
37
|
+
return unless country_code
|
38
|
+
|
39
|
+
check_object_class(country_code, [Symbol, String])
|
40
|
+
check_string_format(country_code.to_s, ISO_CODE_REGEXP)
|
41
|
+
end
|
42
|
+
|
43
|
+
def check_country_code_metadata(metadata)
|
44
|
+
metadata.each do |key, value|
|
45
|
+
check_object_inclusion(key, AVAILABLE_METADATA_KEYS)
|
46
|
+
check_object_class(value, [String])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_dictionary_structure(value)
|
51
|
+
Validation.check_object_class(value, [Hash])
|
52
|
+
|
53
|
+
value.each do |country_code, metadata|
|
54
|
+
Validation.check_object_class(country_code, [Symbol])
|
55
|
+
Validation.check_object_class(metadata, [Hash])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|