defra_ruby_address 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +8 -0
  3. data/README.md +233 -0
  4. data/Rakefile +33 -0
  5. data/bin/console +14 -0
  6. data/bin/setup +8 -0
  7. data/lib/defra_ruby.rb +7 -0
  8. data/lib/defra_ruby/address.rb +28 -0
  9. data/lib/defra_ruby/address/configuration.rb +15 -0
  10. data/lib/defra_ruby/address/ea_address_facade_request.rb +49 -0
  11. data/lib/defra_ruby/address/no_match_error.rb +11 -0
  12. data/lib/defra_ruby/address/response.rb +33 -0
  13. data/lib/defra_ruby/address/services/base_service.rb +14 -0
  14. data/lib/defra_ruby/address/services/ea_address_facade_v1_1_service.rb +16 -0
  15. data/lib/defra_ruby/address/services/ea_address_facade_v1_service.rb +16 -0
  16. data/lib/defra_ruby/address/services/os_places_address_lookup_service.rb +51 -0
  17. data/lib/defra_ruby/address/version.rb +7 -0
  18. data/spec/defra_ruby/address/configuration_spec.rb +18 -0
  19. data/spec/defra_ruby/address/response_spec.rb +70 -0
  20. data/spec/defra_ruby/address/services/ea_address_facade_v1_1_service_spec.rb +73 -0
  21. data/spec/defra_ruby/address/services/ea_address_facade_v1_service_spec.rb +73 -0
  22. data/spec/defra_ruby/address/services/os_places_address_lookup_service_spec.rb +72 -0
  23. data/spec/defra_ruby/address_spec.rb +30 -0
  24. data/spec/examples.txt +27 -0
  25. data/spec/fixtures/ea_address_facade_v1_1_blank.json +8 -0
  26. data/spec/fixtures/ea_address_facade_v1_1_not_found.json +14 -0
  27. data/spec/fixtures/ea_address_facade_v1_1_valid.json +83 -0
  28. data/spec/fixtures/ea_address_facade_v1_blank.json +13 -0
  29. data/spec/fixtures/ea_address_facade_v1_not_found.json +8 -0
  30. data/spec/fixtures/ea_address_facade_v1_valid.json +45 -0
  31. data/spec/fixtures/os_places_address_lookup_blank.json +5 -0
  32. data/spec/fixtures/os_places_address_lookup_not_found.json +6 -0
  33. data/spec/fixtures/os_places_address_lookup_valid.json +56 -0
  34. data/spec/spec_helper.rb +83 -0
  35. data/spec/support/defra_ruby_address.rb +4 -0
  36. data/spec/support/dotenv.rb +4 -0
  37. data/spec/support/pry.rb +7 -0
  38. data/spec/support/shared_examples/handle_request_errors.rb +32 -0
  39. data/spec/support/simplecov.rb +17 -0
  40. data/spec/support/webmock.rb +4 -0
  41. metadata +248 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f47c9a7a1e39ae9d9b7062dc77fe063bf443cbe0
4
+ data.tar.gz: 37cf2259b5bb278a180f89fcb413636b50b4011c
5
+ SHA512:
6
+ metadata.gz: 10198b655e7d18bb9dc59d90bbe9ac1909d0a528bfc9df7a26be3dad6e5438881d501202962d1d102d4298ef9980dfe5b182772fe4bb934b74cd4e1f57cb27dc
7
+ data.tar.gz: b1221cbdd838ba2ee750778987ff652f16b72dc33a20cd5fcef9ae8eaf9ad0248e277af12f3bf61ed63dc5ec01b5b765e5604125f725faf689dad43c677c8ea4
data/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ The Open Government Licence (OGL) Version 3
2
+
3
+ Copyright (c) 2019 Defra
4
+
5
+ This source code is licensed under the Open Government Licence v3.0. To view this
6
+ licence, visit www.nationalarchives.gov.uk/doc/open-government-licence/version/3
7
+ or write to the Information Policy Team, The National Archives, Kew, Richmond,
8
+ Surrey, TW9 4DU.
@@ -0,0 +1,233 @@
1
+ # Defra Ruby Address
2
+
3
+ [![Build Status](https://travis-ci.com/DEFRA/defra-ruby-address.svg?branch=master)](https://travis-ci.com/DEFRA/defra-ruby-address)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/1a0b68efe00098e0734f/maintainability)](https://codeclimate.com/github/DEFRA/defra-ruby-address/maintainability)
5
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/1a0b68efe00098e0734f/test_coverage)](https://codeclimate.com/github/DEFRA/defra-ruby-address/test_coverage)
6
+ [![security](https://hakiri.io/github/DEFRA/defra-ruby-address/master.svg)](https://hakiri.io/github/DEFRA/defra-ruby-address/master)
7
+ [![Gem Version](https://badge.fury.io/rb/defra_ruby_address.svg)](https://badge.fury.io/rb/defra_ruby_address)
8
+ [![Licence](https://img.shields.io/badge/Licence-OGLv3-blue.svg)](http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3)
9
+
10
+ Currently there are a number of Rails based digital services in Defra, talking to a set of address lookups. Behind the scenes these lookups all talk to [OS Places](https://developer.ordnancesurvey.co.uk/os-places-api), yet still for whatever reason we have multiple projects fulfilling this role 😩!
11
+
12
+ This means we are often duplicating code across our digital services, or are stuck having to maintain different environments and code purely to handle working with different lookups. In each case they are doing the same thing, taking a postcode or UPRN, querying OS Places, and returning the results as JSON.
13
+
14
+ So we've created this gem 😁!
15
+
16
+ It's aim is to help us
17
+
18
+ - start to reduce the duplication across projects
19
+ - be consistent in how we peform a lookup
20
+ - be consistent in the response we get and how we handle it
21
+ - move towards a single solution for address lookups across projects
22
+
23
+ ## Installation
24
+
25
+ Add this line to your application's Gemfile
26
+
27
+ ```ruby
28
+ gem "defra_ruby_address"
29
+ ```
30
+
31
+ And then update your dependencies by calling
32
+
33
+ ```bash
34
+ bundle install
35
+ ```
36
+
37
+ ## Configuration
38
+
39
+ You just need to let the gem know the host uri for the address lookup.
40
+
41
+ ```ruby
42
+ # config/initializers/defra_ruby_address.rb
43
+ require "defra_ruby/address"
44
+
45
+ DefraRuby::Address.configure do |config|
46
+ config.host = "http://localhost:9002"
47
+ end
48
+ ```
49
+
50
+ ## Usage
51
+
52
+ The gem interfaces with 2 address lookups
53
+
54
+ - [OS Places Address Lookup](https://github.com/DEFRA/os-places-address-lookup)
55
+ - [EA Address Facade](https://github.com/DEFRA/ea-address-facade) (repo is private)
56
+
57
+ The **EA Address Facade** has 2 versions, so the gem provides 3 separate services a host app can use.
58
+
59
+ ### Response object
60
+
61
+ Each service responds with a `DefraRuby::Address::Response` object. It has the following attributes
62
+
63
+ ```ruby
64
+ response.successful?
65
+ response.results
66
+ response.error
67
+ ```
68
+
69
+ If the call is successful then
70
+
71
+ - `successful?()` will be `true`
72
+ - `results` will contain an array of JSON objects each representing an address. The format of the JSON will depend on the service called
73
+ - `error` will be `nil`
74
+
75
+ If the call is unsuccessful (the query errored or no match was found) then
76
+
77
+ - `successful?()` will be `false`
78
+ - `areas` will be `[]` (an empty array)
79
+ - `error` will contain the error
80
+
81
+ If it's a runtime error, or an error when calling the lookup `error` will contain whatever error was raised.
82
+
83
+ If it's because no match was found `error` will contain an instance of `DefraRuby::Address::NoMatchError`.
84
+
85
+ ### OS Places Address Lookup
86
+
87
+ This was the first address lookup, built for the [Waste Carriers Registration Service](https://github.com/DEFRA/ruby-services-team/tree/master/services/wcr).
88
+
89
+ ```ruby
90
+ response = DefraRuby::Address::OsPlacesAddressLookupService.run("BS1 5AH")
91
+
92
+ puts response.results.first["uprn"] # "340116"
93
+ ```
94
+
95
+ The expected format of each result is
96
+
97
+ ```ruby
98
+ {
99
+ "moniker"=>"340116",
100
+ "uprn"=>"340116",
101
+ "lines"=>[
102
+ "ENVIRONMENT AGENCY",
103
+ "DEANERY ROAD"
104
+ ],
105
+ "town"=>"BRISTOL",
106
+ "postcode"=>"BS1 5AH",
107
+ "easting"=>"358205",
108
+ "northing"=>"172708",
109
+ "country"=>"",
110
+ "dependentLocality"=>"",
111
+ "dependentThroughfare"=>"",
112
+ "administrativeArea"=>"BRISTOL",
113
+ "localAuthorityUpdateDate"=>"",
114
+ "royalMailUpdateDate"=>"",
115
+ "partial"=>"ENVIRONMENT AGENCY, HORIZON HOUSE, DEANERY ROAD, BRISTOL, BS1 5AH",
116
+ "subBuildingName"=>"",
117
+ "buildingName"=>"HORIZON HOUSE",
118
+ "thoroughfareName"=>"DEANERY ROAD",
119
+ "organisationName"=>"ENVIRONMENT AGENCY",
120
+ "buildingNumber"=>"",
121
+ "postOfficeBoxNumber"=>"",
122
+ "departmentName"=>"",
123
+ "doubleDependentLocality"=>""
124
+ }
125
+ ```
126
+
127
+ ### EA Address Facade v1.0
128
+
129
+ This was the second address lookup, built as a means of trying to ensure all services follow the Environment Agency address standard. Its also included general performance and security updates.
130
+
131
+ This version is currently used by the [Waste Exemptions Registration service](https://github.com/DEFRA/ruby-services-team/tree/master/services/wex) and the [Flood Risk Activity Exemptions service](https://github.com/DEFRA/ruby-services-team/tree/master/services/frae).
132
+
133
+ ```ruby
134
+ response = DefraRuby::Address::EaAddressFacadeV1Service.run("BS1 5AH")
135
+
136
+ puts response.results.first["uprn"] # "340116"
137
+ ```
138
+
139
+ The expected format of each result is
140
+
141
+ ```ruby
142
+ {
143
+ "uprn"=>340116,
144
+ "address"=>"ENVIRONMENT AGENCY, HORIZON HOUSE, DEANERY ROAD, BRISTOL, BS1 5AH",
145
+ "organisation"=>"ENVIRONMENT AGENCY",
146
+ "premises"=>"HORIZON HOUSE",
147
+ "street_address"=>"DEANERY ROAD",
148
+ "locality"=>nil,
149
+ "city"=>"BRISTOL",
150
+ "postcode"=>"BS1 5AH",
151
+ "x"=>"358205.03",
152
+ "y"=>"172708.07",
153
+ "coordinate_system"=>nil,
154
+ "state_date"=>"12/10/2009",
155
+ "blpu_state_code"=>nil,
156
+ "postal_address_code"=>nil,
157
+ "logical_status_code"=>nil,
158
+ "source_data_type"=>"dpa"
159
+ }
160
+ ```
161
+
162
+ ### EA Address Facade v1.1
163
+
164
+ This was an iteration of the EA Address Facade. Mainly the format of the request changed as the lookup had been redesigned to run as a single instance for multiple services, whilst allowing each service to differentiate where the calls were coming from.
165
+
166
+ Currently no services are using this version, but the intention is to move the [Waste Exemptions Registration service](https://github.com/DEFRA/ruby-services-team/tree/master/services/wex), [Flood Risk Activity Exemptions service](https://github.com/DEFRA/ruby-services-team/tree/master/services/frae) and [Waste Carriers Registration service](https://github.com/DEFRA/ruby-services-team/tree/master/services/wcr) to it.
167
+
168
+ ```ruby
169
+ response = DefraRuby::Address::EaAddressFacadeV11Service.run("BS1 5AH")
170
+
171
+ puts response.results.first["uprn"] # "340116"
172
+ ```
173
+
174
+ The expected format of each result is
175
+
176
+ ```ruby
177
+ {
178
+ "uprn"=>340116,
179
+ "address"=>"ENVIRONMENT AGENCY, HORIZON HOUSE, DEANERY ROAD, BRISTOL, BS1 5AH",
180
+ "organisation"=>"ENVIRONMENT AGENCY",
181
+ "premises"=>"HORIZON HOUSE",
182
+ "street_address"=>"DEANERY ROAD",
183
+ "locality"=>nil,
184
+ "city"=>"BRISTOL",
185
+ "postcode"=>"BS1 5AH",
186
+ "country"=>"United Kingdom",
187
+ "x"=>358205.03,
188
+ "y"=>172708.06,
189
+ "coordinate_system"=>nil,
190
+ "blpu_state_date"=>"12/10/2009",
191
+ "blpu_state_code"=>2,
192
+ "postal_address_code"=>"D",
193
+ "logical_status_code"=>1,
194
+ "source_data_type"=>"dpa",
195
+ "blpu_state_code_description"=>"In use",
196
+ "classification_code"=>"CO01",
197
+ "classification_code_description"=>"Office / Work Studio",
198
+ "lpi_logical_status_code"=>nil,
199
+ "lpi_logical_status_code_description"=>nil,
200
+ "match"=>1.0,
201
+ "match_description"=>"EXACT",
202
+ "topography_layer_toid"=>"osgb1000002529079737",
203
+ "parent_uprn"=>nil,
204
+ "last_update_date"=>"10/02/2016",
205
+ "status"=>"APPROVED",
206
+ "entry_date"=>"12/10/2009",
207
+ "postal_address_code_description"=>"A record which is linked to PAF",
208
+ "usrn"=>nil,
209
+ "language"=>"EN"
210
+ }
211
+ ```
212
+
213
+ ## Contributing to this project
214
+
215
+ If you have an idea you'd like to contribute please log an issue.
216
+
217
+ All contributions should be submitted via a pull request.
218
+
219
+ ## License
220
+
221
+ THIS INFORMATION IS LICENSED UNDER THE CONDITIONS OF THE OPEN GOVERNMENT LICENCE found at:
222
+
223
+ <http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3>
224
+
225
+ The following attribution statement MUST be cited in your products and applications when using this information.
226
+
227
+ > Contains public sector information licensed under the Open Government license v3
228
+
229
+ ### About the license
230
+
231
+ The Open Government Licence (OGL) was developed by the Controller of Her Majesty's Stationery Office (HMSO) to enable information providers in the public sector to license the use and re-use of their information under a common open licence.
232
+
233
+ It is designed to encourage use and re-use of information freely and flexibly, with only a few conditions.
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "bundler/setup"
5
+ rescue LoadError
6
+ puts "You must `gem install bundler` and `bundle install` to run rake tasks"
7
+ end
8
+
9
+ Bundler::GemHelper.install_tasks
10
+
11
+ # This is wrapped to prevent an error when rake is called in environments where
12
+ # rspec may not be available, e.g. production. As such we don't need to handle
13
+ # the error.
14
+ # rubocop:disable Lint/HandleExceptions
15
+ begin
16
+ require "rspec/core/rake_task"
17
+
18
+ RSpec::Core::RakeTask.new(:spec)
19
+
20
+ task default: :spec
21
+ rescue LoadError
22
+ # no rspec available
23
+ end
24
+
25
+ begin
26
+ require "github_changelog_generator/task"
27
+
28
+ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
29
+ end
30
+ rescue LoadError
31
+ # no changelog available
32
+ end
33
+ # rubocop:enable Lint/HandleExceptions
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "defra_ruby/address"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "defra_ruby/address"
4
+
5
+ module DefraRuby
6
+ # The Defra Ruby packages namespace
7
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "address/configuration"
4
+ require_relative "address/ea_address_facade_request"
5
+ require_relative "address/no_match_error"
6
+ require_relative "address/response"
7
+
8
+ require_relative "address/services/base_service"
9
+ require_relative "address/services/ea_address_facade_v1_1_service"
10
+ require_relative "address/services/ea_address_facade_v1_service"
11
+ require_relative "address/services/os_places_address_lookup_service"
12
+
13
+ module DefraRuby
14
+ module Address
15
+ class << self
16
+ # attr_accessor :configuration
17
+
18
+ def configure
19
+ yield(configuration)
20
+ end
21
+
22
+ def configuration
23
+ @configuration ||= Configuration.new
24
+ @configuration
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Address
5
+ class Configuration
6
+ attr_accessor :timeout, :host, :client_id, :key
7
+
8
+ def initialize
9
+ @timeout = 3
10
+ @client_id = 0
11
+ @key = "client1"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Address
5
+ class EaAddressFacadeRequest
6
+
7
+ def initialize(param_name)
8
+ @param_name = param_name
9
+ end
10
+
11
+ def execute(postcode)
12
+ @postcode = postcode
13
+ Response.new(response_exe)
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :postcode, :param_name
19
+
20
+ def url
21
+ host = DefraRuby::Address.configuration.host
22
+ client_id = DefraRuby::Address.configuration.client_id
23
+ key = DefraRuby::Address.configuration.key
24
+
25
+ File.join(
26
+ host,
27
+ "/address-service/v1/addresses/",
28
+ "postcode?client-id=#{client_id}&key=#{key}&#{param_name}=#{postcode}"
29
+ )
30
+ end
31
+
32
+ def response_exe
33
+ lambda do
34
+ response = RestClient::Request.execute(
35
+ method: :get,
36
+ url: url,
37
+ timeout: DefraRuby::Address.configuration.timeout
38
+ )
39
+ results = JSON.parse(response)["results"]
40
+
41
+ raise DefraRuby::Address::NoMatchError if results.empty?
42
+
43
+ results
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Address
5
+ class NoMatchError < StandardError
6
+ def initialize
7
+ super("No match found")
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRuby
4
+ module Address
5
+ class Response
6
+ attr_reader :error
7
+ attr_reader :results
8
+
9
+ def initialize(response_exe)
10
+ @success = true
11
+ @results = []
12
+ @error = nil
13
+
14
+ capture_response(response_exe)
15
+ end
16
+
17
+ def successful?
18
+ success
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :success
24
+
25
+ def capture_response(response_exe)
26
+ @results = response_exe.call
27
+ rescue StandardError => e
28
+ @error = e
29
+ @success = false
30
+ end
31
+ end
32
+ end
33
+ end