defra_ruby_validators 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +88 -1
  3. data/config/locales/defra_ruby/validators/business_type_validator/en.yml +6 -0
  4. data/config/locales/defra_ruby/validators/email_validator/en.yml +7 -0
  5. data/config/locales/defra_ruby/validators/grid_reference_validator/en.yml +8 -0
  6. data/config/locales/defra_ruby/validators/location_validator/en.yml +6 -0
  7. data/config/locales/defra_ruby/validators/phone_number_validator/en.yml +8 -0
  8. data/config/locales/defra_ruby/validators/position_validator/en.yml +7 -0
  9. data/config/locales/defra_ruby/validators/token_validator/en.yml +7 -0
  10. data/config/locales/defra_ruby/validators/true_false_validator/en.yml +2 -1
  11. data/lib/defra_ruby/validators.rb +10 -0
  12. data/lib/defra_ruby/validators/base_validator.rb +2 -4
  13. data/lib/defra_ruby/validators/business_type_validator.rb +15 -0
  14. data/lib/defra_ruby/validators/companies_house_number_validator.rb +5 -5
  15. data/lib/defra_ruby/validators/concerns/can_validate_characters.rb +19 -0
  16. data/lib/defra_ruby/validators/concerns/can_validate_length.rb +18 -0
  17. data/lib/defra_ruby/validators/concerns/can_validate_presence.rb +18 -0
  18. data/lib/defra_ruby/validators/concerns/can_validate_selection.rb +6 -8
  19. data/lib/defra_ruby/validators/email_validator.rb +28 -0
  20. data/lib/defra_ruby/validators/grid_reference_validator.rb +55 -0
  21. data/lib/defra_ruby/validators/location_validator.rb +15 -0
  22. data/lib/defra_ruby/validators/phone_number_validator.rb +32 -0
  23. data/lib/defra_ruby/validators/position_validator.rb +22 -0
  24. data/lib/defra_ruby/validators/token_validator.rb +27 -0
  25. data/lib/defra_ruby/validators/true_false_validator.rb +2 -2
  26. data/lib/defra_ruby/validators/version.rb +1 -1
  27. data/spec/cassettes/company_no_inactive.yml +14 -14
  28. data/spec/cassettes/company_no_not_found.yml +15 -15
  29. data/spec/cassettes/company_no_valid.yml +14 -14
  30. data/spec/defra_ruby/validators/business_type_validator_spec.rb +30 -0
  31. data/spec/defra_ruby/validators/companies_house_number_validator_spec.rb +15 -15
  32. data/spec/defra_ruby/validators/email_validator_spec.rb +42 -0
  33. data/spec/defra_ruby/validators/grid_reference_validator_spec.rb +49 -0
  34. data/spec/defra_ruby/validators/location_validator_spec.rb +30 -0
  35. data/spec/defra_ruby/validators/phone_number_validator_spec.rb +55 -0
  36. data/spec/defra_ruby/validators/position_validator_spec.rb +47 -0
  37. data/spec/defra_ruby/validators/token_validator_spec.rb +41 -0
  38. data/spec/defra_ruby/validators/true_false_validator_spec.rb +11 -4
  39. data/spec/examples.txt +79 -44
  40. data/spec/spec_helper.rb +4 -0
  41. data/spec/support/helpers/text_generator.rb +17 -0
  42. data/spec/support/helpers/translator.rb +2 -3
  43. data/spec/support/shared_examples/validators/characters_validator.rb +25 -0
  44. data/spec/support/shared_examples/validators/invalid_record.rb +13 -3
  45. data/spec/support/shared_examples/validators/length_validator.rb +25 -0
  46. data/spec/support/shared_examples/validators/presence_validator.rb +25 -0
  47. data/spec/support/shared_examples/validators/selection_validator.rb +11 -11
  48. metadata +70 -19
  49. data/spec/support/dotenv.rb +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9e898f7ee267a5ce4074c4f7c4c04284f3119732
4
- data.tar.gz: fd9c073dc217d74a6468bc25261f6d9338bc24c6
3
+ metadata.gz: 6eb5f30b11f406a2a5c91d2d2eabb709b6e662cc
4
+ data.tar.gz: '049bb686fcc859df2894534e21741d585e0ede29'
5
5
  SHA512:
6
- metadata.gz: d97d8bd20be2314faa28da05224288eb90533113b419d6df3f4d1b0801a9a7f76ddd8e34a3df87b4f7dba7580317e55e315176c5aff38152007d502d49b69d2d
7
- data.tar.gz: 29e0b534deb7e2801ec556c47488846e5be7edaa0f28b80e7433edf3ae69a858504d3f9158084bddd3946b97e5d28aa7b1630853c36f855565337f6f9b422195
6
+ metadata.gz: 5aff6f7c03a848a1f03fff4be8d357d2ca3f8b37ad7d3489f3b76773f20122b8014c596369b27467349b90d331c90c695a8d6a935a7f4794afbedfeb6343fb9c
7
+ data.tar.gz: 05ccedb6de84b3ed7c55303f30e8e9357abebbbf71c1233d1a45df5de7e056d6993c3ca95396cb3e5d438562de9ef8046b71a1c87fa2b1b1934bf1f33895ae56
data/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  [![Build Status](https://travis-ci.com/DEFRA/defra-ruby-validators.svg?branch=master)](https://travis-ci.com/DEFRA/defra-ruby-validators)
4
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/a0f8611f1a879786f642/maintainability)](https://codeclimate.com/github/DEFRA/defra-ruby-validators/maintainability)
5
5
  [![Test Coverage](https://api.codeclimate.com/v1/badges/a0f8611f1a879786f642/test_coverage)](https://codeclimate.com/github/DEFRA/defra-ruby-validators/test_coverage)
6
+ [![security](https://hakiri.io/github/DEFRA/defra-ruby-validators/master.svg)](https://hakiri.io/github/DEFRA/defra-ruby-validators/master)
6
7
  [![Gem Version](https://badge.fury.io/rb/defra_ruby_validators.svg)](https://badge.fury.io/rb/defra_ruby_validators)
7
8
  [![Licence](https://img.shields.io/badge/Licence-OGLv3-blue.svg)](http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3)
8
9
 
@@ -26,6 +27,25 @@ bundle install
26
27
 
27
28
  With this gem installed, a number of active model based validators become available.
28
29
 
30
+ ### Business type
31
+
32
+ This validator checks the value provided is one of our known business types
33
+
34
+ - `soleTrader`
35
+ - `limitedCompany`
36
+ - `partnership`
37
+ - `limitedLiabilityPartnership`
38
+ - `localAuthority`
39
+ - `charity`
40
+
41
+ If blank or not one of these it will return an error.
42
+
43
+ Add it to your model or form object using
44
+
45
+ ```ruby
46
+ validates :business_type, "defra_ruby/validators/business_type": true
47
+ ```
48
+
29
49
  ### Companies House number
30
50
 
31
51
  This validator checks the company registration number provided. Specifically it first checks that it matches a known format. All registration numbers are 8 characters long but can be formatted in the following ways.
@@ -48,6 +68,73 @@ Add it to your model or form object using
48
68
  validates :company_no, "defra_ruby/validators/companies_house_number": true
49
69
  ```
50
70
 
71
+ ### Email
72
+
73
+ This validator checks the value is present and in a format that meets [RFC 2822](https://tools.ietf.org/html/rfc2822) and [RFC 3696](https://tools.ietf.org/html/rfc3696) (we use [validates_email_format_of](https://github.com/validates-email-format-of/validates_email_format_of) to check the format).
74
+
75
+ Add it to your model or form object using
76
+
77
+ ```ruby
78
+ validates :email, "defra_ruby/validators/email": true
79
+ ```
80
+
81
+ ### Grid reference
82
+
83
+ This validator checks the value is present, is in the correct format for an [Ordnance Survey National Grid Reference](https://en.wikipedia.org/wiki/Ordnance_Survey_National_Grid), and that its valid (we use [os_map_ref](https://github.com/DEFRA/os-map-ref) to check the coordinate is valid).
84
+
85
+ Add it to your model or form object using
86
+
87
+ ```ruby
88
+ validates :grid_reference, "defra_ruby/validators/grid_reference": true
89
+ ```
90
+
91
+ ### Location
92
+
93
+ This validator checks the value provided is one of our accepted locations
94
+
95
+ - `england`
96
+ - `northern_ireland`
97
+ - `scotland`
98
+ - `wales`
99
+
100
+ If blank or not one of these it will return an error.
101
+
102
+ Add it to your model or form object using
103
+
104
+ ```ruby
105
+ validates :location, "defra_ruby/validators/location": true
106
+ ```
107
+
108
+ ### Phone number
109
+
110
+ This validator checks the value is present, is not too long (15 is th maximum length for any phone number), and is in the correct format as per [E.164](https://en.wikipedia.org/wiki/E.164) (we use [phonelib](https://github.com/daddyz/phonelib) to check the format).
111
+
112
+ Add it to your model or form object using
113
+
114
+ ```ruby
115
+ validates :phone_number, "defra_ruby/validators/phone_number": true
116
+ ```
117
+
118
+ ### Position
119
+
120
+ This validator checks the value provided for 'position' i.e. someones role or title within an organisation. This is an optional field so the validator has to handle the value being blank. If it's not then it can be no longer than 70 characters and only include letters, spaces, commas, full stops, hyphens and apostrophes else it will return an error.
121
+
122
+ Add it to your model or form object using
123
+
124
+ ```ruby
125
+ validates :position, "defra_ruby/validators/position": true
126
+ ```
127
+
128
+ ### Token
129
+
130
+ This validator checks the value is present and in the correct format, which in this case is that the value has a length of 24. If blank or not in a valid format it will return an error.
131
+
132
+ Add it to your model or form object using
133
+
134
+ ```ruby
135
+ validates :token, "defra_ruby/validators/token": true
136
+ ```
137
+
51
138
  ### True or false
52
139
 
53
140
  This validator checks the value provided is either `"true"` or `"false"`. If blank or not one of these it will return an error.
@@ -55,7 +142,7 @@ This validator checks the value provided is either `"true"` or `"false"`. If bla
55
142
  Add it to your model or form object using
56
143
 
57
144
  ```ruby
58
- validates :company_no, "defra_ruby/validators/true_false": true
145
+ validates :is_a_farmer, "defra_ruby/validators/true_false": true
59
146
  ```
60
147
 
61
148
  ## Contributing to this project
@@ -0,0 +1,6 @@
1
+ en:
2
+ defra_ruby:
3
+ validators:
4
+ BusinessTypeValidator:
5
+ business_type:
6
+ inclusion: "You must answer this question"
@@ -0,0 +1,7 @@
1
+ en:
2
+ defra_ruby:
3
+ validators:
4
+ EmailValidator:
5
+ email:
6
+ blank: "Enter an email address"
7
+ invalid_format: "Enter a valid email address - there’s a mistake in that one"
@@ -0,0 +1,8 @@
1
+ en:
2
+ defra_ruby:
3
+ validators:
4
+ GridReferenceValidator:
5
+ grid_reference:
6
+ blank: Enter a grid reference
7
+ wrong_format: The grid reference should have 2 letters and 10 digits
8
+ invalid: The grid reference is not a valid coordinate
@@ -0,0 +1,6 @@
1
+ en:
2
+ defra_ruby:
3
+ validators:
4
+ LocationValidator:
5
+ location:
6
+ inclusion: "You must answer this question"
@@ -0,0 +1,8 @@
1
+ en:
2
+ defra_ruby:
3
+ validators:
4
+ PhoneNumberValidator:
5
+ phone_number:
6
+ blank: "Enter a telephone number"
7
+ invalid_format: "Enter a valid telephone number"
8
+ too_long: "Check the number you entered - it should have no more than than 15 characters"
@@ -0,0 +1,7 @@
1
+ en:
2
+ defra_ruby:
3
+ validators:
4
+ PositionValidator:
5
+ position:
6
+ invalid: "The position must contain only letters, spaces, commas, full stops, hyphens and apostrophes"
7
+ too_long: "The position must have no more than 70 characters"
@@ -0,0 +1,7 @@
1
+ en:
2
+ defra_ruby:
3
+ validators:
4
+ TokenValidator:
5
+ token:
6
+ invalid_format: "The token is not valid"
7
+ blank: "The token is missing"
@@ -2,4 +2,5 @@ en:
2
2
  defra_ruby:
3
3
  validators:
4
4
  TrueFalseValidator:
5
- inclusion: "You must answer this question"
5
+ attribute:
6
+ inclusion: "You must answer this question"
@@ -6,10 +6,20 @@ require_relative "validators/version"
6
6
  require_relative "validators/configuration"
7
7
  require_relative "validators/companies_house_service"
8
8
 
9
+ require_relative "validators/concerns/can_validate_characters"
10
+ require_relative "validators/concerns/can_validate_length"
11
+ require_relative "validators/concerns/can_validate_presence"
9
12
  require_relative "validators/concerns/can_validate_selection"
10
13
 
11
14
  require_relative "validators/base_validator"
15
+ require_relative "validators/business_type_validator"
12
16
  require_relative "validators/companies_house_number_validator"
17
+ require_relative "validators/email_validator"
18
+ require_relative "validators/grid_reference_validator"
19
+ require_relative "validators/location_validator"
20
+ require_relative "validators/phone_number_validator"
21
+ require_relative "validators/position_validator"
22
+ require_relative "validators/token_validator"
13
23
  require_relative "validators/true_false_validator"
14
24
 
15
25
  module DefraRuby
@@ -6,10 +6,8 @@ module DefraRuby
6
6
 
7
7
  protected
8
8
 
9
- def error_message(attribute: nil, error:)
10
- return I18n.t("defra_ruby.validators.#{class_name}.#{attribute}.#{error}") if attribute
11
-
12
- I18n.t("defra_ruby.validators.#{class_name}.#{error}")
9
+ def error_message(attribute, error)
10
+ options[:message] || I18n.t("defra_ruby.validators.#{class_name}.#{attribute}.#{error}")
13
11
  end
14
12
 
15
13
  private
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Validators
5
+ class BusinessTypeValidator < BaseValidator
6
+ include CanValidateSelection
7
+
8
+ def validate_each(record, _attribute, value)
9
+ valid_options = %w[soleTrader limitedCompany partnership limitedLiabilityPartnership localAuthority charity]
10
+
11
+ value_is_included?(record, :business_type, value, valid_options)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -25,14 +25,14 @@ module DefraRuby
25
25
  def value_is_present?(record, attribute, value)
26
26
  return true if value.present?
27
27
 
28
- record.errors[attribute] << error_message(attribute: attribute, error: "blank")
28
+ record.errors[attribute] << error_message(:company_no, :blank)
29
29
  false
30
30
  end
31
31
 
32
32
  def format_is_valid?(record, attribute, value)
33
33
  return true if value.match?(VALID_COMPANIES_HOUSE_REGISTRATION_NUMBER_REGEX)
34
34
 
35
- record.errors[attribute] << error_message(attribute: attribute, error: "invalid")
35
+ record.errors[attribute] << error_message(:company_no, :invalid)
36
36
  false
37
37
  end
38
38
 
@@ -41,12 +41,12 @@ module DefraRuby
41
41
  when :active
42
42
  true
43
43
  when :inactive
44
- record.errors[attribute] << error_message(attribute: attribute, error: "inactive")
44
+ record.errors[attribute] << error_message(:company_no, :inactive)
45
45
  when :not_found
46
- record.errors[attribute] << error_message(attribute: attribute, error: "not_found")
46
+ record.errors[attribute] << error_message(:company_no, :not_found)
47
47
  end
48
48
  rescue StandardError
49
- record.errors[attribute] << error_message(attribute: attribute, error: "error")
49
+ record.errors[attribute] << error_message(:company_no, :error)
50
50
  end
51
51
 
52
52
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Validators
5
+ module CanValidateCharacters
6
+
7
+ private
8
+
9
+ def value_has_no_invalid_characters?(record, attribute, value)
10
+ # Name fields must contain only letters, spaces, commas, full stops, hyphens and apostrophes
11
+ return true if value.match?(/\A[-a-z\s,.']+\z/i)
12
+
13
+ record.errors[attribute] << error_message(attribute, :invalid)
14
+ false
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Validators
5
+ module CanValidateLength
6
+
7
+ private
8
+
9
+ def value_is_not_too_long?(record, attribute, value, max_length)
10
+ return true if value.length <= max_length
11
+
12
+ record.errors[attribute] << error_message(attribute, :too_long)
13
+ false
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Validators
5
+ module CanValidatePresence
6
+
7
+ private
8
+
9
+ def value_is_present?(record, attribute, value)
10
+ return true if value.present?
11
+
12
+ record.errors[attribute] << error_message(attribute, :blank)
13
+ false
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -3,18 +3,16 @@
3
3
  module DefraRuby
4
4
  module Validators
5
5
  module CanValidateSelection
6
- extend ActiveSupport::Concern
7
6
 
8
- included do
9
- private
7
+ private
10
8
 
11
- def value_is_included?(record, attribute, value, valid_options)
12
- return true if value.present? && valid_options.include?(value)
9
+ def value_is_included?(record, attribute, value, valid_options)
10
+ return true if value.present? && valid_options.include?(value)
13
11
 
14
- record.errors[attribute] << error_message(error: "inclusion")
15
- false
16
- end
12
+ record.errors[attribute] << error_message(attribute, :inclusion)
13
+ false
17
14
  end
15
+
18
16
  end
19
17
  end
20
18
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "validates_email_format_of"
4
+
5
+ module DefraRuby
6
+ module Validators
7
+ class EmailValidator < BaseValidator
8
+ include CanValidatePresence
9
+
10
+ def validate_each(record, attribute, value)
11
+ return false unless value_is_present?(record, :email, value)
12
+
13
+ valid_format?(record, attribute, value)
14
+ end
15
+
16
+ private
17
+
18
+ def valid_format?(record, attribute, value)
19
+ # validate_email_format returns nil if the validation passes
20
+ return true unless ValidatesEmailFormatOf.validate_email_format(value)
21
+
22
+ record.errors[attribute] << error_message(:email, :invalid_format)
23
+ false
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "os_map_ref"
4
+
5
+ module DefraRuby
6
+ module Validators
7
+ class GridReferenceValidator < BaseValidator
8
+ include CanValidatePresence
9
+
10
+ def validate_each(record, attribute, value)
11
+ return false unless value_is_present?(record, :grid_reference, value)
12
+ return false unless valid_format?(record, attribute, value)
13
+
14
+ valid_coordinate?(record, attribute, value)
15
+ end
16
+
17
+ private
18
+
19
+ # Note that OsMapRef will work with less specific coordinates than are
20
+ # required for this service (100m) - so we need to add an additional check
21
+ # rather than just jump straight to confirming if it's a valid coordinate
22
+ def valid_format?(record, attribute, value)
23
+ return true if value.match?(/\A#{grid_reference_pattern}\z/)
24
+
25
+ record.errors[attribute] << error_message(:grid_reference, :wrong_format)
26
+ false
27
+ end
28
+
29
+ def valid_coordinate?(record, attribute, value)
30
+ OsMapRef::Location.for(value).easting
31
+ true
32
+ rescue OsMapRef::Error
33
+ record.errors[attribute] << error_message(:grid_reference, :invalid)
34
+ false
35
+ end
36
+
37
+ def grid_reference_pattern
38
+ [two_letters, optional_space, five_digits, optional_space, five_digits].join
39
+ end
40
+
41
+ def two_letters
42
+ "[A-Za-z]{2}"
43
+ end
44
+
45
+ def five_digits
46
+ '\d{5}'
47
+ end
48
+
49
+ def optional_space
50
+ '\s*'
51
+ end
52
+
53
+ end
54
+ end
55
+ end