defra_ruby_validators 0.1.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -18
  3. data/config/locales/defra_ruby/validators/companies_house_number_validator/en.yml +10 -0
  4. data/lib/defra_ruby/validators.rb +15 -0
  5. data/lib/defra_ruby/validators/base_validator.rb +21 -0
  6. data/lib/defra_ruby/validators/companies_house_number_validator.rb +54 -0
  7. data/lib/defra_ruby/validators/companies_house_service.rb +36 -0
  8. data/lib/defra_ruby/validators/configuration.rb +35 -0
  9. data/lib/defra_ruby/validators/engine.rb +22 -0
  10. data/lib/defra_ruby/validators/version.rb +7 -0
  11. data/lib/defra_ruby_validators.rb +27 -9
  12. data/spec/cassettes/company_no_inactive.yml +14 -14
  13. data/spec/cassettes/company_no_not_found.yml +15 -15
  14. data/spec/cassettes/company_no_valid.yml +14 -14
  15. data/spec/defra_ruby/validators/companies_house_number_validator_spec.rb +88 -0
  16. data/spec/defra_ruby/validators/companies_house_service_spec.rb +58 -0
  17. data/spec/defra_ruby/validators/configuration_spec.rb +49 -0
  18. data/spec/defra_ruby/validators_spec.rb +12 -0
  19. data/spec/examples.txt +36 -27
  20. data/spec/spec_helper.rb +69 -19
  21. data/spec/support/defra_ruby_validators.rb +13 -2
  22. data/spec/support/dotenv.rb +4 -0
  23. data/spec/support/helpers/translator.rb +14 -0
  24. data/spec/support/pry.rb +7 -0
  25. data/spec/support/shared_examples/validators/invalid_record.rb +18 -0
  26. data/spec/support/shared_examples/validators/valid_record.rb +12 -0
  27. data/spec/support/shared_examples/validators/validator.rb +8 -0
  28. data/spec/support/simplecov.rb +17 -0
  29. metadata +37 -19
  30. data/config/locales/defra_ruby_validators/companies_house_number/en.yml +0 -14
  31. data/lib/defra_ruby_validators/companies_house_number_validator.rb +0 -56
  32. data/lib/defra_ruby_validators/companies_house_service.rb +0 -34
  33. data/lib/defra_ruby_validators/engine.rb +0 -20
  34. data/lib/defra_ruby_validators/validators.rb +0 -33
  35. data/lib/defra_ruby_validators/version.rb +0 -5
  36. data/spec/defra_ruby_validators/companies_house_number_validator_spec.rb +0 -125
  37. data/spec/defra_ruby_validators/companies_house_service_spec.rb +0 -55
  38. data/spec/defra_ruby_validators/version_spec.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3e2b90f695b85e87e772c0ff9706b022a889ddfc
4
- data.tar.gz: d0fda70ca250ed7cedc5cb0243f9704858f5a3a3
3
+ metadata.gz: 0a6c04c81d7df4234ebf4905a40680e9f27be96b
4
+ data.tar.gz: 42b56455e1072d95b796c8403453326ce6d6ab85
5
5
  SHA512:
6
- metadata.gz: 6ce3932e23c36d6d657759fcfeb35976bf82d123469d702b18c681c0dc3fb32027309ec6070903d642a26bb1ce47712641dd7843266c85e3a50aca8cb5947f47
7
- data.tar.gz: 1784ad53fb92e0d93550bb583109c84ccff475ed50dc43120467ed2db5f0a86ef1d3304f8b939b7a8c7d3b1f4e10c97bda1a176838261070eb87dbd9aebb6d46
6
+ metadata.gz: f3464caf2e33d2a4dea606ad62728e82becb0416b4122728759e9f7973a877e7d19fcb7957dd175ac5302166ab189a616707b8d25e042f30664b0c9b068ac73a
7
+ data.tar.gz: 8c55a4ffba3ba440ecbefb37cb9de61b654373ea436c07f9c34841440437ba4105f90171b7058472f83b4376ef7e78fc92d40c8d26fd0c2fb88edc9b3561b545
data/README.md CHANGED
@@ -45,24 +45,7 @@ A company can be in various states for example liquidation, which means for the
45
45
  Add it to your model or form object using
46
46
 
47
47
  ```ruby
48
- validates :company_no, "defra_ruby_validators/companies_house_number": true
49
- ```
50
-
51
- A locale hint plus help text is also available for your views, that details what a registration number is and the restrictions, e.g
52
-
53
- ```erb
54
- <span class="form-hint"><%= t("defra_validators.companies_house_number.hint") %></span>
55
-
56
- <div class="form-group">
57
- <details>
58
- <summary>
59
- <span class="summary"><%= t("defra_validators.companies_house_number.help.heading") %></span>
60
- </summary>
61
- <div class="panel panel-border-narrow">
62
- <p><%= t("defra_validators.companies_house_number.help.#{@form.business_type}") %></p>
63
- </div>
64
- </details>
65
- </div>
48
+ validates :company_no, "defra_ruby/validators/companies_house_number": true
66
49
  ```
67
50
 
68
51
  ## Contributing to this project
@@ -0,0 +1,10 @@
1
+ en:
2
+ defra_ruby:
3
+ validators:
4
+ CompaniesHouseNumberValidator:
5
+ company_no:
6
+ blank: Enter a company registration number
7
+ invalid: "Enter a valid number - it should have 8 digits, or 2 letters followed by 6 digits, or 2 letters followed by 5 digits and another letter. If your number has only 7 digits, enter it with a zero at the start."
8
+ not_found: Companies House couldn't find a company with this number
9
+ inactive: Your company must be registered as an active company
10
+ error: There was an error connecting with Companies House. Hopefully this is a one off and will work if you try again.
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_model"
4
+
5
+ require_relative "validators/version"
6
+ require_relative "validators/configuration"
7
+ require_relative "validators/companies_house_service"
8
+
9
+ require_relative "validators/base_validator"
10
+ require_relative "validators/companies_house_number_validator"
11
+
12
+ module DefraRuby
13
+ module Validators
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Validators
5
+ class BaseValidator < ActiveModel::EachValidator
6
+
7
+ protected
8
+
9
+ def error_message(attribute, error)
10
+ I18n.t("defra_ruby.validators.#{class_name}.#{attribute}.#{error}")
11
+ end
12
+
13
+ private
14
+
15
+ def class_name
16
+ self.class.name.split("::").last
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Validators
5
+ class CompaniesHouseNumberValidator < BaseValidator
6
+
7
+ # Examples we need to validate are
8
+ # 10997904, 09764739
9
+ # SC534714, CE000958
10
+ # IP00141R, IP27702R, SP02252R
11
+ # https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/426891/uniformResourceIdentifiersCustomerGuide.pdf
12
+ VALID_COMPANIES_HOUSE_REGISTRATION_NUMBER_REGEX = Regexp.new(
13
+ /\A(\d{8,8}$)|([a-zA-Z]{2}\d{6}$)|([a-zA-Z]{2}\d{5}[a-zA-Z]{1}$)\z/i
14
+ ).freeze
15
+
16
+ def validate_each(record, attribute, value)
17
+ return false unless value_is_present?(record, attribute, value)
18
+ return false unless format_is_valid?(record, attribute, value)
19
+
20
+ validate_with_companies_house(record, attribute, value)
21
+ end
22
+
23
+ private
24
+
25
+ def value_is_present?(record, attribute, value)
26
+ return true if value.present?
27
+
28
+ record.errors[attribute] << error_message(attribute, "blank")
29
+ false
30
+ end
31
+
32
+ def format_is_valid?(record, attribute, value)
33
+ return true if value.match?(VALID_COMPANIES_HOUSE_REGISTRATION_NUMBER_REGEX)
34
+
35
+ record.errors[attribute] << error_message(attribute, "invalid")
36
+ false
37
+ end
38
+
39
+ def validate_with_companies_house(record, attribute, value)
40
+ case CompaniesHouseService.new(value).status
41
+ when :active
42
+ true
43
+ when :inactive
44
+ record.errors[attribute] << error_message(attribute, "inactive")
45
+ when :not_found
46
+ record.errors[attribute] << error_message(attribute, "not_found")
47
+ end
48
+ rescue StandardError
49
+ record.errors[attribute] << error_message(attribute, "error")
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rest-client"
4
+
5
+ module DefraRuby
6
+ module Validators
7
+ class CompaniesHouseService
8
+ def initialize(company_no)
9
+ @company_no = company_no
10
+ @url = "#{DefraRuby::Validators.configuration.companies_house_host}#{@company_no}"
11
+ @api_key = DefraRuby::Validators.configuration.companies_house_api_key
12
+ end
13
+
14
+ def status
15
+ response = RestClient::Request.execute(
16
+ method: :get,
17
+ url: @url,
18
+ user: @api_key,
19
+ password: ""
20
+ )
21
+
22
+ json = JSON.parse(response)
23
+
24
+ status_is_allowed?(json["company_status"]) ? :active : :inactive
25
+ rescue RestClient::ResourceNotFound
26
+ :not_found
27
+ end
28
+
29
+ private
30
+
31
+ def status_is_allowed?(status)
32
+ %w[active voluntary-arrangement].include?(status)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Validators
5
+ class << self
6
+ attr_accessor :configuration
7
+ end
8
+
9
+ def self.configure
10
+ self.configuration ||= Configuration.new
11
+ yield(configuration)
12
+ end
13
+
14
+ class Configuration
15
+ ATTRIBUTES = %i[
16
+ companies_house_host
17
+ companies_house_api_key
18
+ ].freeze
19
+
20
+ attr_accessor(*ATTRIBUTES)
21
+
22
+ def initialize
23
+ @companies_house_host = "https://api.companieshouse.gov.uk/company/"
24
+ @companies_house_api_key = nil
25
+ end
26
+
27
+ def ensure_valid
28
+ missing_attributes = ATTRIBUTES.select { |a| public_send(a).nil? }
29
+ return true if missing_attributes.empty?
30
+
31
+ raise "The following DefraRuby::Validators configuration attributes are missing: #{missing_attributes}"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "defra_ruby/validators"
4
+
5
+ module DefraRuby
6
+ module Validators
7
+ # Engine used to load in the custom validations
8
+ class Engine < ::Rails::Engine
9
+ isolate_namespace DefraRuby::Validators
10
+
11
+ # Add a load path for this specific Engine
12
+ config.autoload_paths += Dir[File.join(config.root, "lib", "**")]
13
+
14
+ # Load I18n translation files from engine before loading ones from the host app
15
+ # This means values in the host app can override those in the engine
16
+ config.before_initialize do
17
+ engine_locales = Dir["#{config.root}/config/locales/**/*.yml"]
18
+ config.i18n.load_path = engine_locales + config.i18n.load_path
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Validators
5
+ VERSION = "1.0.0"
6
+ end
7
+ end
@@ -1,14 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "defra_ruby_validators/engine"
3
+ require "defra_ruby/validators/engine"
4
4
 
5
+ # This breaks from the typical pattern of calling the root file in lib after the
6
+ # root namespace e.g. defra_ruby.rb
7
+ # The specific intent for this gem (engine) is to be used in our services rails
8
+ # engines i.e. an engine mounted in an engine.
9
+ #
10
+ # The standard pattern is to have an engine.rb in the relevant namespace. Hence
11
+ # in this project we have lib/defra_ruby/validators/engine.rb. When it comes to
12
+ # requiring this project in host engine this means it needs to require that
13
+ # file explicitly. For example in lib/waste_exemptions_engine/engine.rb the
14
+ # reference would be
15
+ #
16
+ # require "defra_ruby/validators/engine"
17
+ #
18
+ # That's fine, but it does mean this file becomes meaningless. Its not
19
+ # referenced by our specs as they refer to lib/defra_ruby/validators/validators.rb
20
+ # It's not referenced by engine.rb because it also references validators.rb.
21
+ #
22
+ # However if we call it defra_ruby_validators.rb and include a require to the
23
+ # engine, then the host engine can instead just do the following
24
+ #
25
+ # require "defra_ruby_validators"
26
+ #
27
+ # This makes the require statement consistent with the name of the gem, makes
28
+ # implementation a little simpler, and if we build up a suite of these engines
29
+ # makes them a little clearer to distinguish in the host engine's engine.rb.
5
30
  module DefraRubyValidators
6
- # See lib/defra_ruby_validators/validators.rb for the main content.
7
- # We have this file which just require's engine.rb to support using the gem
8
- # in a rails project.
9
- # For our test suite, we just want the typical listing of `require "filex"`,
10
- # as the engine references using Rails.
11
- # We also have the gem setup to support being configured from the host app.
12
- # This is all done in `validators.rb`, which is picked up by `engine.rb` as
13
- # well.
31
+ # The Defra Ruby packages namespace
14
32
  end
@@ -12,7 +12,7 @@ http_interactions:
12
12
  Accept-Encoding:
13
13
  - gzip, deflate
14
14
  User-Agent:
15
- - rest-client/2.0.2 (darwin17.3.0 x86_64) ruby/2.4.2p198
15
+ - rest-client/2.0.2 (darwin18.5.0 x86_64) ruby/2.4.2p198
16
16
  Host:
17
17
  - api.companieshouse.gov.uk
18
18
  Authorization:
@@ -22,14 +22,6 @@ http_interactions:
22
22
  code: 200
23
23
  message: OK
24
24
  headers:
25
- Date:
26
- - Mon, 28 Jan 2019 09:38:50 GMT
27
- Content-Type:
28
- - application/json
29
- Content-Length:
30
- - '979'
31
- Connection:
32
- - keep-alive
33
25
  Access-Control-Allow-Credentials:
34
26
  - 'true'
35
27
  Access-Control-Allow-Headers:
@@ -44,18 +36,26 @@ http_interactions:
44
36
  - '3600'
45
37
  Cache-Control:
46
38
  - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
39
+ Content-Type:
40
+ - application/json
41
+ Date:
42
+ - Mon, 13 May 2019 10:51:59 GMT
47
43
  Pragma:
48
44
  - no-cache
45
+ Server:
46
+ - CompaniesHouse
49
47
  X-Ratelimit-Limit:
50
48
  - '600'
51
49
  X-Ratelimit-Remain:
52
- - '596'
50
+ - '597'
53
51
  X-Ratelimit-Reset:
54
- - '1548668445'
52
+ - '1557745019'
55
53
  X-Ratelimit-Window:
56
54
  - 5m
57
- Server:
58
- - CompaniesHouse
55
+ Content-Length:
56
+ - '979'
57
+ Connection:
58
+ - keep-alive
59
59
  body:
60
60
  encoding: UTF-8
61
61
  string: '{"sic_codes":["82990"],"company_number":"07281919","has_been_liquidated":false,"accounts":{"last_accounts":{"made_up_to":"2013-06-30","type":"total-exemption-small"},"accounting_reference_date":{"day":"30","month":"06"}},"last_full_members_list_date":"2014-06-11","status":"active","type":"ltd","date_of_creation":"2010-06-11","registered_office_address":{"postal_code":"HA8
@@ -63,5 +63,5 @@ http_interactions:
63
63
  Elizabeth House","address_line_2":"54-58 High Street"},"undeliverable_registered_office_address":false,"company_name":"DIRECT
64
64
  SKIPS UK LTD","annual_return":{"last_made_up_to":"2014-06-11"},"jurisdiction":"england-wales","etag":"1cdef5bc2a020b3e9003b086033b64b78bcb28f6","company_status":"dissolved","has_insolvency_history":false,"has_charges":false,"links":{"self":"/company/07281919","filing_history":"/company/07281919/filing-history","officers":"/company/07281919/officers"},"date_of_cessation":"2016-01-05","can_file":false}'
65
65
  http_version:
66
- recorded_at: Mon, 28 Jan 2019 09:38:50 GMT
66
+ recorded_at: Mon, 13 May 2019 10:51:59 GMT
67
67
  recorded_with: VCR 4.0.0
@@ -12,7 +12,7 @@ http_interactions:
12
12
  Accept-Encoding:
13
13
  - gzip, deflate
14
14
  User-Agent:
15
- - rest-client/2.0.2 (darwin17.3.0 x86_64) ruby/2.4.2p198
15
+ - rest-client/2.0.2 (darwin18.5.0 x86_64) ruby/2.4.2p198
16
16
  Host:
17
17
  - api.companieshouse.gov.uk
18
18
  Authorization:
@@ -22,14 +22,6 @@ http_interactions:
22
22
  code: 404
23
23
  message: Not Found
24
24
  headers:
25
- Date:
26
- - Mon, 28 Jan 2019 09:38:50 GMT
27
- Content-Type:
28
- - application/json
29
- Content-Length:
30
- - '70'
31
- Connection:
32
- - keep-alive
33
25
  Access-Control-Allow-Credentials:
34
26
  - 'true'
35
27
  Access-Control-Allow-Headers:
@@ -44,21 +36,29 @@ http_interactions:
44
36
  - '3600'
45
37
  Cache-Control:
46
38
  - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
39
+ Content-Type:
40
+ - application/json
41
+ Date:
42
+ - Mon, 13 May 2019 10:51:59 GMT
47
43
  Pragma:
48
44
  - no-cache
45
+ Server:
46
+ - CompaniesHouse
49
47
  X-Ratelimit-Limit:
50
48
  - '600'
51
49
  X-Ratelimit-Remain:
52
- - '597'
50
+ - '598'
53
51
  X-Ratelimit-Reset:
54
- - '1548668445'
52
+ - '1557745019'
55
53
  X-Ratelimit-Window:
56
54
  - 5m
57
- Server:
58
- - CompaniesHouse
55
+ Content-Length:
56
+ - '70'
57
+ Connection:
58
+ - keep-alive
59
59
  body:
60
60
  encoding: UTF-8
61
- string: '{"errors":[{"error":"company-profile-not-found","type":"ch:service"}]}'
61
+ string: '{"errors":[{"type":"ch:service","error":"company-profile-not-found"}]}'
62
62
  http_version:
63
- recorded_at: Mon, 28 Jan 2019 09:38:50 GMT
63
+ recorded_at: Mon, 13 May 2019 10:51:59 GMT
64
64
  recorded_with: VCR 4.0.0
@@ -12,7 +12,7 @@ http_interactions:
12
12
  Accept-Encoding:
13
13
  - gzip, deflate
14
14
  User-Agent:
15
- - rest-client/2.0.2 (darwin17.3.0 x86_64) ruby/2.4.2p198
15
+ - rest-client/2.0.2 (darwin18.5.0 x86_64) ruby/2.4.2p198
16
16
  Host:
17
17
  - api.companieshouse.gov.uk
18
18
  Authorization:
@@ -22,14 +22,6 @@ http_interactions:
22
22
  code: 200
23
23
  message: OK
24
24
  headers:
25
- Date:
26
- - Sun, 27 Jan 2019 23:57:58 GMT
27
- Content-Type:
28
- - application/json
29
- Content-Length:
30
- - '1178'
31
- Connection:
32
- - keep-alive
33
25
  Access-Control-Allow-Credentials:
34
26
  - 'true'
35
27
  Access-Control-Allow-Headers:
@@ -44,22 +36,30 @@ http_interactions:
44
36
  - '3600'
45
37
  Cache-Control:
46
38
  - no-store, no-cache, must-revalidate, post-check=0, pre-check=0
39
+ Content-Type:
40
+ - application/json
41
+ Date:
42
+ - Mon, 13 May 2019 10:51:59 GMT
47
43
  Pragma:
48
44
  - no-cache
45
+ Server:
46
+ - CompaniesHouse
49
47
  X-Ratelimit-Limit:
50
48
  - '600'
51
49
  X-Ratelimit-Remain:
52
- - '598'
50
+ - '599'
53
51
  X-Ratelimit-Reset:
54
- - '1548633621'
52
+ - '1557745019'
55
53
  X-Ratelimit-Window:
56
54
  - 5m
57
- Server:
58
- - CompaniesHouse
55
+ Content-Length:
56
+ - '1178'
57
+ Connection:
58
+ - keep-alive
59
59
  body:
60
60
  encoding: UTF-8
61
61
  string: '{"type":"ltd","company_name":"0800 WASTE LTD.","has_insolvency_history":false,"accounts":{"next_due":"2019-09-30","next_made_up_to":"2018-12-31","next_accounts":{"overdue":false,"period_start_on":"2018-01-01","due_on":"2019-09-30","period_end_on":"2018-12-31"},"accounting_reference_date":{"month":"12","day":"31"},"last_accounts":{"period_end_on":"2017-12-31","period_start_on":"2017-01-01","made_up_to":"2017-12-31"},"overdue":false},"undeliverable_registered_office_address":false,"etag":"0ec9d00cab0ffee2ef1f5d59f4f714fa5b1618f5","company_number":"09360070","registered_office_address":{"postal_code":"SM3
62
62
  9ND","locality":"Sutton","region":"Surrey","address_line_1":"21 Haslam Avenue"},"jurisdiction":"england-wales","date_of_creation":"2014-12-18","company_status":"active","has_charges":false,"sic_codes":["38110"],"last_full_members_list_date":"2015-12-18","confirmation_statement":{"overdue":false,"next_made_up_to":"2020-01-23","last_made_up_to":"2019-01-23","next_due":"2020-02-06"},"links":{"self":"/company/09360070","filing_history":"/company/09360070/filing-history","officers":"/company/09360070/officers"},"registered_office_is_in_dispute":false,"can_file":true}'
63
63
  http_version:
64
- recorded_at: Sun, 27 Jan 2019 23:57:58 GMT
64
+ recorded_at: Mon, 13 May 2019 10:51:58 GMT
65
65
  recorded_with: VCR 4.0.0