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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d4b40991721f4eb047e7060a428f3d85593cc4ce3dd15bb427d95ed629cbb37
4
- data.tar.gz: cfedbc59ad70b411b385ba55813e5ebf32247ebaf2b2628f324b3d77799b6aed
3
+ metadata.gz: c02ace863de99e8b6d41ff12185285c5c4bff2131e45d23873981cf0115e03ee
4
+ data.tar.gz: 81ab67bc56f3de3edf78432cdb679ede3237d7fdcb40266f666ed6713c3dde35
5
5
  SHA512:
6
- metadata.gz: 7f012c7724dddab12ef370a57d7e5f5d00d6f556cbd5bb4aa5f0b11c33298bcc2eee4a523cce73dbcb1e669c4824d57bd14c8a67780741bb3186b65ed568ac68
7
- data.tar.gz: d51f55008b3cfd58a48e312af82a9538f00e75f6e857b0601d83c684bbfdd30612f031e89ee809811ccc99614e91af1653f761106cda6f00f1c7d34959bab1c4
6
+ metadata.gz: 6b6ff3493c540f62461a948d05de2ee4206ee0c2851d366eaf46e632802f74d7c9fc21c1a232404eef724197e70ee1194ec99ec3dea3c2363c53879352736799
7
+ data.tar.gz: 8973da310ae9ba856ca2553c3d1e8c27fdd3f0a20ff03044b1487539a735f6548ee9b8f51974fc4635421297fcb95320ab1a9cc1bc2be6939a4aa354d7c7b94f
data/.codeclimate.yml ADDED
@@ -0,0 +1,4 @@
1
+ plugins:
2
+ rubocop:
3
+ enabled: true
4
+ channel: rubocop-1-31-0
@@ -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.7
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
- Enabled: false
12
+ EnforcedStyle: double_quotes
9
13
 
10
- Metrics/BlockLength:
11
- Exclude:
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
- Max: 80
29
+ Exclude:
30
+ - "spec/**/*_spec.rb"
31
+ - "*.gemspec"
22
32
 
23
33
  Naming/MemoizedInstanceVariableName:
24
- EnforcedStyleForLeadingUnderscores: optional
34
+ EnforcedStyleForLeadingUnderscores: optional
35
+
36
+ Gemspec/RequireMFA:
37
+ Enabled: false
data/.simplecov ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "simplecov_json_formatter"
4
+
5
+ SimpleCov.start
6
+ SimpleCov.formatters = SimpleCov::Formatter::JSONFormatter
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) - #3
9
- * Remove `countries` attr_reader to use `CompanyNumber::Number#valid_countries` - #3
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' private information, such as a physical or email
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's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
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
@@ -2,5 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- # Specify your gem's dependencies in company_number.gemspec
5
+ # Specify your gem"s dependencies in company_number.gemspec
6
6
  gemspec
7
+
8
+ gem "rubocop", "< 1.32" # Keep .codeclimate.yml channel in sync
data/README.md CHANGED
@@ -1,15 +1,19 @@
1
1
  # CompanyNumber
2
2
 
3
- [![Build Status](https://github.com/victorauthiat/company_number/actions/workflows/build.yml/badge.svg)](https://github.com/victorauthiat/company_number/actions/workflows/build.yml)
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's Gemfile:
13
+ Add this line to your application"s Gemfile:
10
14
 
11
15
  ```ruby
12
- gem 'company_number'
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('123456789', :fr)
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.valid_country?
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('123') == CompanyNumber.parse('123')
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'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).
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
- RuboCop::RakeTask.new
9
+ RSpec::Core::RakeTask.new(:test)
10
+ RuboCop::RakeTask.new(:rubocop)
11
11
 
12
- task default: %i[spec rubocop]
12
+ task default: %i[rubocop test]
data/bin/setup CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bash
2
2
  set -euo pipefail
3
- IFS=$'\n\t'
3
+ IFS=$"\n\t"
4
4
  set -vx
5
5
 
6
6
  bundle install
@@ -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 = 'Validate a company number according to a country code'
12
- spec.homepage = 'https://github.com/victorauthiat/company_number'
13
- spec.license = 'MIT'
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 'bundler', '~> 2.2.25'
23
- spec.add_development_dependency 'pry', '~> 0.14.1'
24
- spec.add_development_dependency 'rake', '~> 13.0.6'
25
- spec.add_development_dependency 'rspec', '~> 3.10.0'
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
@@ -7,7 +7,7 @@ at:
7
7
 
8
8
  be:
9
9
  country: Belgium
10
- name: Numéro d'entreprise Vestigingseenheidsnummer
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'immatriculation
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
- check_param_type(company_number, [String])
7
- check_param_type(country_code, [NilClass, Symbol, String])
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
- !valid_country? || valid_for_country?(@country_code)
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
- check_param_type(country_code, [Symbol])
40
-
41
- !!(@company_number =~ country_code_regexp(country_code))
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 country_code_regexp(country_code)
56
- regexp = CompanyNumber.dictionary.dig(country_code, :regexp)
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 check_param_type(param, expected_classes = [])
62
- return if expected_classes.include?(param.class)
67
+ def country_code_present_and_valid_country?
68
+ !!@country_code && valid_for_country?(@country_code)
69
+ end
63
70
 
64
- raise ArgumentError,
65
- "Expect class of #{param} to be #{expected_classes.join(', ')}"
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CompanyNumber
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.3"
5
5
  end