From 23a1075bc3aae9d6495723e5406ce8a5a0913a9b Mon Sep 17 00:00:00 2001
From: Scott Wenborne <scott@initfothe.com>
Date: Tue, 10 Apr 2018 16:02:23 +0100
Subject: [PATCH] WIP setup for Postcodes.io

---
 lib/geocoder/lookup.rb                   |  1 +
 lib/geocoder/lookups/postcodes_io.rb     | 28 +++++++++++++++++
 lib/geocoder/results/postcodes_io.rb     | 38 ++++++++++++++++++++++++
 test/fixtures/postcodes_io_malvern_hills | 36 ++++++++++++++++++++++
 test/fixtures/postcodes_io_no_results    |  4 +++
 test/test_helper.rb                      | 12 ++++++++
 test/unit/lookup_test.rb                 |  2 +-
 test/unit/lookups/postcodes_io_test.rb   | 21 +++++++++++++
 8 files changed, 141 insertions(+), 1 deletion(-)
 create mode 100644 lib/geocoder/lookups/postcodes_io.rb
 create mode 100644 lib/geocoder/results/postcodes_io.rb
 create mode 100644 test/fixtures/postcodes_io_malvern_hills
 create mode 100644 test/fixtures/postcodes_io_no_results
 create mode 100644 test/unit/lookups/postcodes_io_test.rb

diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb
index b756f768..73cf81e1 100644
--- a/lib/geocoder/lookup.rb
+++ b/lib/geocoder/lookup.rb
@@ -48,6 +48,7 @@ module Geocoder
         :smarty_streets,
         :okf,
         :postcode_anywhere_uk,
+        :postcodes_io,
         :geoportail_lu,
         :ban_data_gouv_fr,
         :test,
diff --git a/lib/geocoder/lookups/postcodes_io.rb b/lib/geocoder/lookups/postcodes_io.rb
new file mode 100644
index 00000000..16957132
--- /dev/null
+++ b/lib/geocoder/lookups/postcodes_io.rb
@@ -0,0 +1,28 @@
+require 'geocoder/lookups/base'
+require 'geocoder/results/postcodes_io'
+
+module Geocoder::Lookup
+  class PostcodesIo < Base
+    def name
+      'Postcodes.io'
+    end
+
+    def query_url(query)
+      str = query.sanitized_text.gsub(/\s/, '')
+      format('%s://%s/%s', protocol, 'api.postcodes.io/postcodes', str)
+    end
+
+    def supported_protocols
+      [:https]
+    end
+
+    private
+
+    def results(query)
+      response = fetch_data(query)
+      return [] if response.nil? || response['status'] != 200 || response.empty?
+
+      [response['result']]
+    end
+  end
+end
diff --git a/lib/geocoder/results/postcodes_io.rb b/lib/geocoder/results/postcodes_io.rb
new file mode 100644
index 00000000..a9d1194f
--- /dev/null
+++ b/lib/geocoder/results/postcodes_io.rb
@@ -0,0 +1,38 @@
+require 'geocoder/results/base'
+
+module Geocoder::Result
+  class PostcodesIo < Base
+    def coordinates
+      [latitude, longitude]
+    end
+
+    def latitude
+      @data['latitude'].to_f
+    end
+
+    def longitude
+      @data['longitude'].to_f
+    end
+
+    def quality
+      @data['quality']
+    end
+
+    def postcode
+      @data['postcode']
+    end
+
+    def county
+      @data['admin_county']
+    end
+    alias state county
+
+    def country
+      'United Kingdom'
+    end
+
+    def country_code
+      'UK'
+    end
+  end
+end
diff --git a/test/fixtures/postcodes_io_malvern_hills b/test/fixtures/postcodes_io_malvern_hills
new file mode 100644
index 00000000..7a43cfc1
--- /dev/null
+++ b/test/fixtures/postcodes_io_malvern_hills
@@ -0,0 +1,36 @@
+{
+    "status": 200,
+    "result": {
+        "postcode": "WR2 6NJ",
+        "quality": 1,
+        "eastings": 381676,
+        "northings": 259425,
+        "country": "England",
+        "nhs_ha": "West Midlands",
+        "longitude": -2.26972239639173,
+        "latitude": 52.2327158260535,
+        "european_electoral_region": "West Midlands",
+        "primary_care_trust": "Worcestershire",
+        "region": "West Midlands",
+        "lsoa": "Malvern Hills 002B",
+        "msoa": "Malvern Hills 002",
+        "incode": "6NJ",
+        "outcode": "WR2",
+        "parliamentary_constituency": "West Worcestershire",
+        "admin_district": "Malvern Hills",
+        "parish": "Hallow",
+        "admin_county": "Worcestershire",
+        "admin_ward": "Hallow",
+        "ccg": "NHS South Worcestershire",
+        "nuts": "Worcestershire",
+        "codes": {
+            "admin_district": "E07000235",
+            "admin_county": "E10000034",
+            "admin_ward": "E05007851",
+            "parish": "E04010305",
+            "parliamentary_constituency": "E14001035",
+            "ccg": "E38000166",
+            "nuts": "UKG12"
+        }
+    }
+}
diff --git a/test/fixtures/postcodes_io_no_results b/test/fixtures/postcodes_io_no_results
new file mode 100644
index 00000000..0c929cda
--- /dev/null
+++ b/test/fixtures/postcodes_io_no_results
@@ -0,0 +1,4 @@
+{
+    "status": 404,
+    "error": "Postcode not found"
+}
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 4857dfed..961216d6 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -330,6 +330,18 @@ module Geocoder
       end
     end
 
+    require 'geocoder/lookups/postcodes_io'
+    class PostcodesIo
+      private
+      def fixture_prefix
+        'postcodes_io'
+      end
+
+      def default_fixture_filename
+        "#{fixture_prefix}_malvern_hills"
+      end
+    end
+
     require 'geocoder/lookups/geoportail_lu'
     class GeoportailLu
       private
diff --git a/test/unit/lookup_test.rb b/test/unit/lookup_test.rb
index 7f21877f..1b8a13bd 100644
--- a/test/unit/lookup_test.rb
+++ b/test/unit/lookup_test.rb
@@ -24,7 +24,7 @@ class LookupTest < GeocoderTestCase
 
   def test_query_url_contains_values_in_params_hash
     Geocoder::Lookup.all_services_except_test.each do |l|
-      next if [:freegeoip, :maxmind_local, :telize, :pointpin, :geoip2, :maxmind_geoip2, :mapbox, :ipdata_co, :ipinfo_io, :ipapi_com].include? l # does not use query string
+      next if [:freegeoip, :maxmind_local, :telize, :pointpin, :geoip2, :maxmind_geoip2, :mapbox, :ipdata_co, :ipinfo_io, :ipapi_com, :postcodes_io].include? l # does not use query string
       set_api_key!(l)
       url = Geocoder::Lookup.get(l).query_url(Geocoder::Query.new(
         "test", :params => {:one_in_the_hand => "two in the bush"}
diff --git a/test/unit/lookups/postcodes_io_test.rb b/test/unit/lookups/postcodes_io_test.rb
new file mode 100644
index 00000000..30fd7378
--- /dev/null
+++ b/test/unit/lookups/postcodes_io_test.rb
@@ -0,0 +1,21 @@
+# encoding: utf-8
+require 'test_helper'
+
+class PostcodesIoTest < GeocoderTestCase
+
+  def setup
+    Geocoder.configure(lookup: :postcodes_io)
+  end
+
+  def test_result_on_postcode_search
+    results = Geocoder.search('WR26NJ')
+
+    assert_equal 1, results.size
+    assert_equal 'Worcestershire', results.first.county
+    assert_equal [52.2327158260535, -2.26972239639173], results.first.coordinates
+  end
+
+  def test_no_results
+    assert_equal [], Geocoder.search('no results')
+  end
+end
-- 
GitLab