diff --git a/app/controllers/uprn_address_spike_controller.rb b/app/controllers/uprn_address_spike_controller.rb new file mode 100644 index 000000000..9876dd8b0 --- /dev/null +++ b/app/controllers/uprn_address_spike_controller.rb @@ -0,0 +1,27 @@ +class UprnAddressSpikeController < ApplicationController + def show + if params[:uprn] || params[:address] + + if params[:uprn] + uprn = params[:uprn] + service = UprnClient.new(uprn) + service.call + if service.error.present? + @error = "no match" + else + @address_returned = UprnDataPresenter.new(service.result) + end + elsif params[:address] + address = params[:address] + service = AddressClient.new(address) + service.call + if service.error.present? + @error = "no match" + else + @addresses_returned = service.result&.map { |r| AddressDataPresenter.new(r) } + end + end + end + render "content/uprn_address_spike" + end +end diff --git a/app/services/address_client.rb b/app/services/address_client.rb new file mode 100644 index 000000000..e70971ba5 --- /dev/null +++ b/app/services/address_client.rb @@ -0,0 +1,51 @@ +require "net/http" + +class AddressClient + attr_reader :address + attr_accessor :error + + ADDRESS = "api.os.uk".freeze + PATH = "/search/places/v1/find".freeze + + def initialize(address) + @address = address + end + + def call + unless response.is_a?(Net::HTTPSuccess) && result.present? + @error = "Address is not recognised. Check the address, or enter the UPRN" + end + rescue JSON::ParserError + @error = "Address is not recognised. Check the address, or enter the UPRN" + end + + def result + @result ||= JSON.parse(response.body)["results"]&.map { |address| address["DPA"] } + end + +private + + def http_client + client = Net::HTTP.new(ADDRESS, 443) + client.use_ssl = true + client.verify_mode = OpenSSL::SSL::VERIFY_PEER + client.max_retries = 3 + client.read_timeout = 10 # seconds + client + end + + def endpoint_uri + uri = URI(PATH) + params = { + query: address, + key: ENV["OS_DATA_KEY"], + matchprecision: 3, + } + uri.query = URI.encode_www_form(params) + uri.to_s + end + + def response + @response ||= http_client.request_get(endpoint_uri) + end +end diff --git a/app/services/address_data_presenter.rb b/app/services/address_data_presenter.rb new file mode 100644 index 000000000..1cc3d1273 --- /dev/null +++ b/app/services/address_data_presenter.rb @@ -0,0 +1,25 @@ +require "net/http" + +class AddressDataPresenter + attr_reader :data + + def initialize(data) + @data = data + end + + def uprn + data["UPRN"] + end + + def address + data["ADDRESS"] + end + + def match + data["MATCH"] + end + + def match_description + data["MATCH_DESCRIPTION"] + end +end diff --git a/app/views/content/uprn_address_spike.html.erb b/app/views/content/uprn_address_spike.html.erb new file mode 100644 index 000000000..5f9d2b74a --- /dev/null +++ b/app/views/content/uprn_address_spike.html.erb @@ -0,0 +1,39 @@ +
+ + + +
+ +
+ + + +
+ +<% if params[:uprn] %> +

UPRN given:

+

<%= params[:uprn] %>

+ <% if @error.present? %> + <%= @error %> + <% elsif @address_returned.present? %> +

Output:

+

<%= @address_returned.address_line1 %>

+

<%= @address_returned.address_line2 %>

+

<%= @address_returned.town_or_city %>

+

<%= @address_returned.postcode %>

+ <% end %> +<% elsif params[:address] %> +

Address given:

+

<%= params[:address] %>

+ <% if @error.present? %> + <%= @error %> + <% elsif @addresses_returned.present? %> +

Output:

+ <% @addresses_returned.each do |address_returned| %> +

Address: <%= address_returned.address %>

+

UPRN: <%= address_returned.uprn %>

+

Confidence: <%= address_returned.match%> (<%= address_returned.match_description %>)

+
+ <% end %> + <% end %> +<% end %> diff --git a/config/routes.rb b/config/routes.rb index 99ac0cc31..1c425e39d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,6 @@ # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html Rails.application.routes.draw do + get "uprn-address-spike", to: "uprn_address_spike#show" mount_sidekiq = -> { mount Sidekiq::Web => "/sidekiq" } authenticate(:user, :support?.to_proc, &mount_sidekiq)