Skip to content

Commit

Permalink
Add support for Open Location Codes as a search provider
Browse files Browse the repository at this point in the history
  • Loading branch information
tomhughes committed Jan 11, 2019
1 parent 6263764 commit 703344a
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 1 deletion.
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ gem "secure_headers"
# Load canonical-rails to generate canonical URLs
gem "canonical-rails"

# Load plus_codes for plus code searching
gem "plus_codes"

# Used to generate logstash friendly log files
gem "logstasher"

Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ GEM
parser (2.5.3.0)
ast (~> 2.4.0)
pg (0.21.0)
plus_codes (0.2.1)
poltergeist (1.18.1)
capybara (>= 2.1, < 4)
cliver (~> 0.3.1)
Expand Down Expand Up @@ -427,6 +428,7 @@ DEPENDENCIES
openstreetmap-deadlock_retry (>= 1.3.0)
paperclip (~> 5.2)
pg (~> 0.18)
plus_codes
poltergeist
psych
puma (~> 3.7)
Expand Down
23 changes: 22 additions & 1 deletion app/controllers/geocoder_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class GeocoderController < ApplicationController
require "cgi"
require "uri"
require "rexml/document"
require "plus_codes/open_location_code"

before_action :authorize_web
before_action :set_locale
Expand All @@ -17,7 +18,9 @@ def search
@sources.push "osm_nominatim_reverse"
@sources.push "geonames_reverse" if defined?(GEONAMES_USERNAME)
elsif @params[:query]
if @params[:query] =~ /^\d{5}(-\d{4})?$/
if olc.full?(@params[:query])
@sources.push "plus_code"
elsif @params[:query] =~ /^\d{5}(-\d{4})?$/
@sources.push "osm_nominatim"
elsif @params[:query] =~ /^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW])\s*[0-9][ABD-HJLNP-UW-Z]{2})$/i
@sources.push "osm_nominatim"
Expand Down Expand Up @@ -81,6 +84,20 @@ def search_latlon
end
end

def search_plus_code
code_area = olc.decode(params[:query])

@results = [{ :lat => code_area.latitude_center,
:lon => code_area.longitude_center,
:min_lat => code_area.south_latitude,
:max_lat => code_area.north_latitude,
:min_lon => code_area.west_longitude,
:max_lon => code_area.east_longitude,
:name => params[:query] }]

render :action => "results"
end

def search_ca_postcode
# get query parameters
query = params[:query]
Expand Down Expand Up @@ -350,4 +367,8 @@ def dms_to_decdeg(captures)
end
{ :lat => lat, :lon => lon }
end

def olc
@olc ||= PlusCodes::OpenLocationCode.new
end
end
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ en:
search:
title:
latlon: 'Results from <a href="https://openstreetmap.org/">Internal</a>'
plus_code: 'Results from <a href="https://plus.codes/">Plus Codes</a>'
ca_postcode: 'Results from <a href="https://geocoder.ca/">Geocoder.CA</a>'
osm_nominatim: 'Results from <a href="https://nominatim.openstreetmap.org/">OpenStreetMap Nominatim</a>'
geonames: 'Results from <a href="http://www.geonames.org/">GeoNames</a>'
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@
# geocoder
get "/search" => "geocoder#search"
get "/geocoder/search_latlon" => "geocoder#search_latlon"
get "/geocoder/search_plus_code" => "geocoder#search_plus_code"
get "/geocoder/search_ca_postcode" => "geocoder#search_ca_postcode"
get "/geocoder/search_osm_nominatim" => "geocoder#search_osm_nominatim"
get "/geocoder/search_geonames" => "geocoder#search_geonames"
Expand Down
79 changes: 79 additions & 0 deletions test/controllers/geocoder_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ def test_routes
{ :path => "/geocoder/search_latlon", :method => :get },
{ :controller => "geocoder", :action => "search_latlon" }
)
assert_routing(
{ :path => "/geocoder/search_plus_code", :method => :get },
{ :controller => "geocoder", :action => "search_plus_code" }
)
assert_routing(
{ :path => "/geocoder/search_ca_postcode", :method => :get },
{ :controller => "geocoder", :action => "search_ca_postcode" }
Expand Down Expand Up @@ -233,6 +237,23 @@ def test_identify_latlon_sw_dms
end
end

##
# Test identification of plus codes
def test_identify_plus_code
[
"6PH57VP3+PQ",
"6GCRPR6C+24",
"8FWC2345+G6",
"8FWC2345+G6G",
"8fwc2345+",
"8FWCX400+"
].each do |code|
post :search, :params => { :query => code }
assert_response :success
assert_equal %w[plus_code], assigns(:sources)
end
end

##
# Test identification of US zipcodes
def test_identify_us_postcode
Expand Down Expand Up @@ -317,6 +338,64 @@ def test_search_latlon_digits
results_check_error "Latitude or longitude are out of range"
end

##
# Test the plus code search
def test_search_plus_code
get :search_plus_code, :xhr => true,
:params => { :query => "6PH57VP3+PQ", :zoom => 10,
:minlon => -0.559, :minlat => 51.217,
:maxlon => 0.836, :maxlat => 51.766 }
results_check "name" => "6PH57VP3+PQ",
"lat" => 1.2868125, "lon" => 103.85443749999999,
"min-lat" => 1.2867499999999998, "max-lat" => 1.2868749999999998,
"min-lon" => 103.85437499999999, "max-lon" => 103.85449999999999

get :search_plus_code, :xhr => true,
:params => { :query => "6GCRPR6C+24", :zoom => 10,
:minlon => -0.559, :minlat => 51.217,
:maxlon => 0.836, :maxlat => 51.766 }
results_check "name" => "6GCRPR6C+24",
"lat" => -1.2899375, "lon" => 36.8203125,
"min-lat" => -1.29, "max-lat" => -1.289875,
"min-lon" => 36.82025, "max-lon" => 36.820375

get :search_plus_code, :xhr => true,
:params => { :query => "8FWC2345+G6", :zoom => 10,
:minlon => -0.559, :minlat => 51.217,
:maxlon => 0.836, :maxlat => 51.766 }
results_check "name" => "8FWC2345+G6",
"lat" => 48.0063125, "lon" => 8.058062500000002,
"min-lat" => 48.00625, "max-lat" => 48.006375,
"min-lon" => 8.058000000000002, "max-lon" => 8.058125000000002

get :search_plus_code, :xhr => true,
:params => { :query => "8FWC2345+G6G", :zoom => 10,
:minlon => -0.559, :minlat => 51.217,
:maxlon => 0.836, :maxlat => 51.766 }
results_check "name" => "8FWC2345+G6G",
"lat" => 48.0063125, "lon" => 8.058078125000002,
"min-lat" => 48.0063, "max-lat" => 48.006325000000004,
"min-lon" => 8.058062500000002, "max-lon" => 8.058093750000001

get :search_plus_code, :xhr => true,
:params => { :query => "8fwc2345+", :zoom => 10,
:minlon => -0.559, :minlat => 51.217,
:maxlon => 0.836, :maxlat => 51.766 }
results_check "name" => "8fwc2345+",
"lat" => 48.00625, "lon" => 8.058750000000002,
"min-lat" => 48.005, "max-lat" => 48.0075,
"min-lon" => 8.057500000000001, "max-lon" => 8.06

get :search_plus_code, :xhr => true,
:params => { :query => "8FWCX400+", :zoom => 10,
:minlon => -0.559, :minlat => 51.217,
:maxlon => 0.836, :maxlat => 51.766 }
results_check "name" => "8FWCX400+",
"lat" => 48.975, "lon" => 8.125,
"min-lat" => 48.95, "max-lat" => 49.0,
"min-lon" => 8.1, "max-lon" => 8.15
end

##
# Test the Canadian postcode search
def test_search_ca_postcode
Expand Down

0 comments on commit 703344a

Please sign in to comment.