Skip to content
Snippets Groups Projects
Commit 84e827ac authored by Marc Tobias Metten's avatar Marc Tobias Metten
Browse files

implement opencagedata geocoder, incl tests and fixtures

parent ffe15f0b
No related branches found
No related tags found
No related merge requests found
......@@ -427,6 +427,17 @@ The following is a comparison of the supported geocoding APIs. The "Limitations"
* **Terms of Service**: http://wiki.openstreetmap.org/wiki/Nominatim_usage_policy
* **Limitations**: Please limit request rate to 1 per second and include your contact information in User-Agent headers (eg: `Geocoder.configure(:http_headers => { "User-Agent" => "your contact info" })`). Data licensed under CC-BY-SA (you must provide attribution).
#### OpenCageData (`:opencagedata`)
* **API key**: required
* **Key signup**: http://geocoder.opencagedata.com
* **Quota**: 2500 requests / day, then ability to purchase more (free during beta)
* **Region**: world
* **SSL support**: yes
* **Languages**: worldwide
* **Documentation**: http://geocoder.opencagedata.com/api.html
* **Limitations**: Data licensed under CC-BY-SA or (you must provide attribution).
#### Yandex (`:yandex`)
* **API key**: none
......
......@@ -32,6 +32,7 @@ module Geocoder
:yandex,
:nominatim,
:mapquest,
:opencagedata,
:ovi,
:here,
:baidu,
......
require 'geocoder/lookups/base'
require 'geocoder/results/opencagedata'
module Geocoder::Lookup
class Opencagedata < Base
def name
"OpenCageData"
end
def query_url(query)
"#{protocol}://api.opencagedata.com/geocode/v1/json?key=#{configuration.api_key}&q=#{url_query_string(query)}"
end
def required_api_key_parts
["key"]
end
private
def valid_response?(response)
status = parse_json(response.body)["status"]
super(response) and status['message'] == 'OK'
end
def results(query)
data = fetch_data(query)
(data && data['results']) || []
end
def query_url_params(query)
params = {
:query => query.sanitized_text,
:language => (query.language || configuration.language)
}.merge(super)
unless (bounds = query.options[:bounds]).nil?
params[:bounds] = bounds.map{ |point| "%f,%f" % point }.join(',')
end
params
end
end
end
require 'geocoder/results/base'
module Geocoder::Result
class Opencagedata < Base
def poi
%w[stadium bus_stop tram_stop].each do |key|
return @data['components'][key] if @data['components'].key?(key)
end
return nil
end
def house_number
@data['components']['house_number']
end
def address
@data['formatted']
end
def street
%w[road pedestrian highway].each do |key|
return @data['components'][key] if @data['components'].key?(key)
end
return nil
end
def city
%w[city town village hamlet].each do |key|
return @data['components'][key] if @data['components'].key?(key)
end
return nil
end
def village
@data['components']['village']
end
def state
@data['components']['state']
end
alias_method :state_code, :state
def postal_code
@data['components']['postcode'].to_s
end
def county
@data['components']['county']
end
def country
@data['components']['country']
end
def country_code
@data['components']['country_code']
end
def suburb
@data['components']['suburb']
end
def coordinates
[@data['lat'].to_f, @data['lon'].to_f]
end
def self.response_attributes
%w[boundingbox license
formatted stadium]
end
response_attributes.each do |a|
unless method_defined?(a)
define_method a do
@data[a]
end
end
end
end
end
{
"licenses" : [
{
"name" : "CC-BY-SA",
"url" : "http://creativecommons.org/licenses/by-sa/3.0/"
},
{
"name" : "ODbL",
"url" : "http://opendatacommons.org/licenses/odbl/summary/"
}
],
"rate" : {
"limit" : 2500,
"remaining" : 2488,
"reset" : 1407369600
},
"results" : [
{
"annotations" : {
"OSM" : {
"url" : "http://www.openstreetmap.org/?mlat=40.75052&mlon=-73.99355#map=17/40.75052/-73.99355"
},
"timezone" : {
"name" : "America/New_York",
"now_in_dst" : 1,
"offset_sec" : -14400,
"offset_string" : -400,
"short_name" : "EDT"
}
},
"bounds" : {
"northeast" : {
"lat" : 40.751161,
"lng" : -73.9925922
},
"southwest" : {
"lat" : 40.7498531,
"lng" : -73.9944444
}
},
"components" : {
"country" : "United States of America",
"country_code" : "US",
"county" : "New York County",
"house_number" : 46,
"neighbourhood" : "Koreatown",
"postcode" : 10011,
"road" : "West 31st Street",
"city": "New York City",
"stadium" : "Madison Square Garden",
"state" : "New York",
"state_district" : "New York City"
},
"confidence" : 10,
"formatted" : "46, West 31st Street, Koreatown, New York County, 10011, New York City, New York, United States of America, Madison Square Garden",
"geometry" : {
"lat" : 40.7505247,
"lng" : -73.9935500942432
}
}
],
"status" : {
"code" : 200,
"message" : "OK"
},
"thanks" : "For using an OpenCage Data API",
"timestamp" : {
"created_http" : "Wed, 06 Aug 2014 12:53:59 GMT",
"created_unix" : 1407329639
},
"total_results" : 1,
"we_are_hiring" : "http://lokku.com/#jobs"
}
\ No newline at end of file
{
"licenses" : [
{
"name" : "CC-BY-SA",
"url" : "http://creativecommons.org/licenses/by-sa/3.0/"
},
{
"name" : "ODbL",
"url" : "http://opendatacommons.org/licenses/odbl/summary/"
}
],
"rate" : {
"limit" : 2500,
"remaining" : 2487,
"reset" : 1407369600
},
"results" : [],
"status" : {
"code" : 200,
"message" : "OK"
},
"thanks" : "For using an OpenCage Data API",
"timestamp" : {
"created_http" : "Wed, 06 Aug 2014 12:56:03 GMT",
"created_unix" : 1407329763
},
"total_results" : 0,
"we_are_hiring" : "http://lokku.com/#jobs"
}
# encoding: utf-8
$: << File.join(File.dirname(__FILE__), "..", "..")
require 'test_helper'
class OpencagedataTest < GeocoderTestCase
def setup
Geocoder.configure(lookup: :opencagedata)
set_api_key!(:opencagedata)
end
def test_result_components
result = Geocoder.search("Madison Square Garden, New York, NY").first
assert_equal "West 31st Street", result.street
assert_match /46, West 31st Street, Koreatown, New York County, 10011, New York City, New York, United States of America/, result.address
end
def test_opencagedata_query_url_contains_bounds
lookup = Geocoder::Lookup::Opencagedata.new
url = lookup.query_url(Geocoder::Query.new(
"Some street",
:bounds => [[40.0, -120.0], [39.0, -121.0]]
))
assert_match(/bounds=40.0+%2C-120.0+%2C39.0+%2C-121.0+/, url)
end
def test_no_results
results = Geocoder.search("no results")
assert_equal 0, results.length
end
def test_opencagedata_reverse_url
query = Geocoder::Query.new([45.423733, -75.676333])
assert_match /\bquery=45.423733%2C-75.676333\b/, query.url
end
# def test_raises_exception_when_over_query_limit
# Geocoder.configure(:always_raise => [Geocoder::OverQueryLimitError])
# l = Geocoder::Lookup.get(:opencagedata)
# assert_raises Geocoder::OverQueryLimitError do
# l.send(:results, Geocoder::Query.new("over limit"))
# end
# end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment