postman_paf 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/gem-push.yml +48 -0
  3. data/.github/workflows/gem-test.yml +22 -0
  4. data/.gitignore +17 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +36 -0
  7. data/CHANGELOG.md +5 -0
  8. data/CODE_OF_CONDUCT.md +84 -0
  9. data/Gemfile +6 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +174 -0
  12. data/Rakefile +12 -0
  13. data/bin/console +15 -0
  14. data/bin/setup +8 -0
  15. data/lib/postman_paf/converter.rb +65 -0
  16. data/lib/postman_paf/exceptions/exceptions.rb +29 -0
  17. data/lib/postman_paf/exceptions/last_part_exceptions.rb +36 -0
  18. data/lib/postman_paf/exceptions/rule_3_exceptions.rb +35 -0
  19. data/lib/postman_paf/exceptions/rule_5_and_7_exceptions.rb +24 -0
  20. data/lib/postman_paf/exceptions/rule_6_exceptions.rb +48 -0
  21. data/lib/postman_paf/exceptions/which_exception.rb +103 -0
  22. data/lib/postman_paf/printable_address.rb +35 -0
  23. data/lib/postman_paf/rules/address_builder.rb +30 -0
  24. data/lib/postman_paf/rules/building_number.rb +35 -0
  25. data/lib/postman_paf/rules/rule_1.rb +27 -0
  26. data/lib/postman_paf/rules/rule_2.rb +23 -0
  27. data/lib/postman_paf/rules/rule_3.rb +45 -0
  28. data/lib/postman_paf/rules/rule_4.rb +24 -0
  29. data/lib/postman_paf/rules/rule_5.rb +35 -0
  30. data/lib/postman_paf/rules/rule_6.rb +69 -0
  31. data/lib/postman_paf/rules/rule_7.rb +33 -0
  32. data/lib/postman_paf/rules/rules.rb +71 -0
  33. data/lib/postman_paf/rules/which_rule.rb +40 -0
  34. data/lib/postman_paf/validator.rb +65 -0
  35. data/lib/postman_paf/version.rb +5 -0
  36. data/lib/postman_paf.rb +32 -0
  37. data/postman_paf.gemspec +53 -0
  38. metadata +210 -0
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PostmanPAF
4
+ # Validator class for user input. Verifies input contains required PAF
5
+ # address elements for mailing.
6
+ # @see https://www.poweredbypaf.com/wp-content/uploads/2017/07/Latest-Programmers_guide_Edition-7-Version-6.pdf Page 12
7
+ class Validator
8
+ POST_TOWN = 'postTown'
9
+ POSTCODE = 'postcode'
10
+
11
+ # @param input the object to be validated.
12
+ # @return Validator object.
13
+ def initialize(input:)
14
+ @input = input
15
+ end
16
+
17
+ # Verifies input meets minimum requirements for address conversion.
18
+ # @raise [ArgumentError] if input is not a Hash or Array.
19
+ # @return [nil] if Hash or Array meet address conversion
20
+ # requirements.
21
+ def validate
22
+ if @input.is_a?(Hash)
23
+ validate_single_address
24
+ elsif @input.is_a?(Array) && @input.size.positive?
25
+ validate_multiple_addresses
26
+ else
27
+ raise ArgumentError, 'Conversion input must be either a hash containing data for an address, or an array of hashes each containing data for an address'
28
+ end
29
+ nil
30
+ end
31
+
32
+ private
33
+
34
+ # Verifies input of single Hash contains required address elements.
35
+ # @raise [ArgumentError] if Hash is missing required address elements.
36
+ # @return [nil] if Hash contains required address elements.
37
+ def validate_single_address
38
+ raise ArgumentError, "Hash of address data must contain 'postTown' and 'postcode' keys" unless criteria_for_paf_address?(hash: @input)
39
+ end
40
+
41
+ # Verifies input of Array contains a Hash as each element and that
42
+ # each Hash contains required address elements.
43
+ # @raise [ArgumentError] if an Array elements is not a Hash.
44
+ # @raise [ArgumentError] if Hash element is missing required
45
+ # address elements.
46
+ # @return [nil] if each Array element is a Hash which contains
47
+ # required PAF address elements.
48
+ def validate_multiple_addresses
49
+ @input.each do |element|
50
+ raise ArgumentError, 'Each address element in the array must be a hash' unless element.is_a?(Hash)
51
+
52
+ raise ArgumentError, "Hash of address data must contain 'postTown' and 'postcode' keys" unless criteria_for_paf_address?(hash: element)
53
+ end
54
+ end
55
+
56
+ # Checks if postTown and postcode keys exist within a Hash
57
+ # (Ruby or JSON Hash syntax).
58
+ # @param hash [Hash] the Hash object.
59
+ # @return [Boolean] whether both keys were found.
60
+ def criteria_for_paf_address?(hash:)
61
+ hash = hash.transform_keys { |k| SimpleSymbolize.camelize(k).to_s }
62
+ hash.keys.include?(POST_TOWN) && hash.keys.include?(POSTCODE)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PostmanPAF
4
+ VERSION = '0.3.0'
5
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'logger'
5
+ require 'simple_symbolize'
6
+
7
+ Dir['./lib/postman_paf/**/*.rb'].each do |file|
8
+ require file
9
+ end
10
+
11
+ module PostmanPAF
12
+ # Initialise Logger output.
13
+ LOG = Logger.new($stdout)
14
+ LOG.formatter = proc { |severity, datetime, _progname, msg| "[#{datetime} #{severity} PostmanPAF] -- #{msg}\n" }
15
+
16
+ # Converts PAF address data to printable format based on Royal Mail
17
+ # rules and exceptions.
18
+ # @see https://www.poweredbypaf.com/wp-content/uploads/2017/07/Latest-Programmers_guide_Edition-7-Version-6.pdf
19
+ # @param input [Hash, Array<Hash>] PAF address data.
20
+ # @param max_line_length [Integer, String] optional argument to set
21
+ # max length of printable address lines 1-5.
22
+ # @param logging [Boolean] optional argument to log rule and
23
+ # exception(s) applied during conversion.
24
+ # @raises [ArgumentError] if invalid input given.
25
+ # @return [Hash, Array<Hash>, nil] converted address data, nil if
26
+ # conversion data ineligible for conversion.
27
+ def self.convert(input, max_line_length: nil, logging: false)
28
+ Validator.new(input: input).validate
29
+
30
+ Converter.new(paf_address_data: input, max_line_length: max_line_length, logging: logging).convert
31
+ end
32
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/postman_paf/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'postman_paf'
7
+ spec.version = PostmanPAF::VERSION
8
+ spec.authors = ['Driver and Vehicle Licensing Agency (DVLA)', 'Mark Isaac']
9
+ spec.email = ['mark.isaac@dvla.gov.uk']
10
+
11
+ spec.summary = 'Convert PAF (Postcode Address File) addresses to a printable format for an envelope or address label.'
12
+
13
+ spec.description = <<-DESCRIPTION
14
+ Unofficial gem to apply Royal Mail Rules & Exceptions to PAF (Postcode Address File) addresses when converting to a printable format. Based on the Royal Mail Programmers' Guide:
15
+ https://www.poweredbypaf.com/wp-content/uploads/2017/07/Latest-Programmers_guide_Edition-7-Version-6.pdf,'Formatting a PAF address for printing' (page 27). Addresses conversions
16
+ aim to resemble addresses returned by Royal Mail Find a PostCode as accurately as possible: https://www.royalmail.com/find-a-postcode.
17
+ DESCRIPTION
18
+
19
+ # spec.homepage = "TODO: Put your gem's website or public repo URL here."
20
+ spec.license = 'MIT'
21
+ spec.required_ruby_version = '>= 3.0'
22
+
23
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'https://mygemserver.com'"
24
+
25
+ # spec.metadata['homepage_uri'] = spec.homepage
26
+ # spec.metadata['source_code_uri'] = "TODO: Put your gem's public repo URL here."
27
+ # spec.metadata['changelog_uri'] = "TODO: Put your gem's CHANGELOG.md URL here."
28
+
29
+ # Specify which files should be added to the gem when it is released.
30
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
31
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
32
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
33
+ end
34
+ spec.bindir = 'exe'
35
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
36
+ spec.require_paths = ['lib']
37
+
38
+ # Uncomment to register a new dependency of your gem
39
+ # spec.add_dependency "example-gem", "~> 1.0"
40
+
41
+ # For more information and examples about making a new gem, checkout our
42
+ # guide at: https://bundler.io/guides/creating_gem.html
43
+ spec.add_development_dependency 'bundler-audit', '~> 0.9'
44
+ spec.add_development_dependency 'hash_miner', '~> 1.1'
45
+ spec.add_development_dependency 'pry', '~> 0.14'
46
+ spec.add_development_dependency 'rake', '~> 13.0'
47
+ spec.add_development_dependency 'rspec', '~> 3.12'
48
+ spec.add_development_dependency 'rubocop', '~> 1.54'
49
+ spec.add_development_dependency 'simplecov', '~> 0.22'
50
+ spec.add_development_dependency 'simplecov-console', '~> 0.9'
51
+
52
+ spec.add_runtime_dependency 'simple_symbolize', '~> 4.0'
53
+ end
metadata ADDED
@@ -0,0 +1,210 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: postman_paf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Driver and Vehicle Licensing Agency (DVLA)
8
+ - Mark Isaac
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2024-02-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler-audit
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '0.9'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '0.9'
28
+ - !ruby/object:Gem::Dependency
29
+ name: hash_miner
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.1'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.1'
42
+ - !ruby/object:Gem::Dependency
43
+ name: pry
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '0.14'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '0.14'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '13.0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '13.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rspec
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '3.12'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '3.12'
84
+ - !ruby/object:Gem::Dependency
85
+ name: rubocop
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '1.54'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '1.54'
98
+ - !ruby/object:Gem::Dependency
99
+ name: simplecov
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '0.22'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '0.22'
112
+ - !ruby/object:Gem::Dependency
113
+ name: simplecov-console
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: '0.9'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - "~>"
124
+ - !ruby/object:Gem::Version
125
+ version: '0.9'
126
+ - !ruby/object:Gem::Dependency
127
+ name: simple_symbolize
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - "~>"
131
+ - !ruby/object:Gem::Version
132
+ version: '4.0'
133
+ type: :runtime
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - "~>"
138
+ - !ruby/object:Gem::Version
139
+ version: '4.0'
140
+ description: |2
141
+ Unofficial gem to apply Royal Mail Rules & Exceptions to PAF (Postcode Address File) addresses when converting to a printable format. Based on the Royal Mail Programmers' Guide:
142
+ https://www.poweredbypaf.com/wp-content/uploads/2017/07/Latest-Programmers_guide_Edition-7-Version-6.pdf,'Formatting a PAF address for printing' (page 27). Addresses conversions
143
+ aim to resemble addresses returned by Royal Mail Find a PostCode as accurately as possible: https://www.royalmail.com/find-a-postcode.
144
+ email:
145
+ - mark.isaac@dvla.gov.uk
146
+ executables: []
147
+ extensions: []
148
+ extra_rdoc_files: []
149
+ files:
150
+ - ".github/workflows/gem-push.yml"
151
+ - ".github/workflows/gem-test.yml"
152
+ - ".gitignore"
153
+ - ".rspec"
154
+ - ".rubocop.yml"
155
+ - CHANGELOG.md
156
+ - CODE_OF_CONDUCT.md
157
+ - Gemfile
158
+ - LICENSE.txt
159
+ - README.md
160
+ - Rakefile
161
+ - bin/console
162
+ - bin/setup
163
+ - lib/postman_paf.rb
164
+ - lib/postman_paf/converter.rb
165
+ - lib/postman_paf/exceptions/exceptions.rb
166
+ - lib/postman_paf/exceptions/last_part_exceptions.rb
167
+ - lib/postman_paf/exceptions/rule_3_exceptions.rb
168
+ - lib/postman_paf/exceptions/rule_5_and_7_exceptions.rb
169
+ - lib/postman_paf/exceptions/rule_6_exceptions.rb
170
+ - lib/postman_paf/exceptions/which_exception.rb
171
+ - lib/postman_paf/printable_address.rb
172
+ - lib/postman_paf/rules/address_builder.rb
173
+ - lib/postman_paf/rules/building_number.rb
174
+ - lib/postman_paf/rules/rule_1.rb
175
+ - lib/postman_paf/rules/rule_2.rb
176
+ - lib/postman_paf/rules/rule_3.rb
177
+ - lib/postman_paf/rules/rule_4.rb
178
+ - lib/postman_paf/rules/rule_5.rb
179
+ - lib/postman_paf/rules/rule_6.rb
180
+ - lib/postman_paf/rules/rule_7.rb
181
+ - lib/postman_paf/rules/rules.rb
182
+ - lib/postman_paf/rules/which_rule.rb
183
+ - lib/postman_paf/validator.rb
184
+ - lib/postman_paf/version.rb
185
+ - postman_paf.gemspec
186
+ homepage:
187
+ licenses:
188
+ - MIT
189
+ metadata: {}
190
+ post_install_message:
191
+ rdoc_options: []
192
+ require_paths:
193
+ - lib
194
+ required_ruby_version: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - ">="
197
+ - !ruby/object:Gem::Version
198
+ version: '3.0'
199
+ required_rubygems_version: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - ">="
202
+ - !ruby/object:Gem::Version
203
+ version: '0'
204
+ requirements: []
205
+ rubygems_version: 3.3.7
206
+ signing_key:
207
+ specification_version: 4
208
+ summary: Convert PAF (Postcode Address File) addresses to a printable format for an
209
+ envelope or address label.
210
+ test_files: []