diff --git a/.travis.yml b/.travis.yml index eec4b155657a367487e1e2e594fcf5bd983a0e3b..a285f44f3ebaec1559f784c7c8742ff60acd035c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,13 @@ language: ruby sudo: false env: - - DB= - - DB=sqlite - - DB=postgres - - DB=mysql + global: + - JRUBY_OPTS=--2.0 + matrix: + - DB= + - DB=sqlite + - DB=postgres + - DB=mysql rvm: - 1.9.3 - 2.0.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index b116f8bc19e740f63cd0394a06e0f66506af507b..f96ad928c4ec395b0a4a3f2d928551fe0702a694 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ Changelog Major changes to Geocoder for each release. Please see the Git log for complete list of changes. +1.3.3 (2016 Apr 4) +------------------ +* Fix incorrect gem version number. + +1.3.2 (2016 Apr 1) +------------------ +* Remove :yahoo lookup (service was discontinued Mar 31) (thanks github.com/galiat). +* Add support for LatLon.io service (thanks github.com/evanmarks). +* Add support for IpInfo.io service (thanks github.com/rehan, akostyuk). +* Add support for Pelias/Mapzen service (thanks github.com/RealScout). + 1.3.1 (2016 Feb 20) ------------------- * Warn about upcoming discontinuation of :yahoo lookup (thanks github.com/galiat). diff --git a/README.md b/README.md index 546fbdaa77f2d8180f081e73804e44adfaadfedc..a0a05344e8dca4b77a5fcdd7332adb4a68c7fadf 100644 --- a/README.md +++ b/README.md @@ -434,19 +434,6 @@ The [Google Places Details API](https://developers.google.com/places/documentati * **Terms of Service**: https://developers.google.com/places/policies * **Limitations**: "If your application displays Places API data on a page or view that does not also display a Google Map, you must show a "Powered by Google" logo with that data." -#### Yahoo BOSS (`:yahoo`) -**Warning - [this API will be discontinued on March 31.](https://developer.yahoo.com/boss/placefinder/)** - -* **API key**: requires OAuth consumer key and secret (set `Geocoder.configure(:api_key => [key, secret])`) -* **Key signup**: http://developer.yahoo.com/boss/geo/ -* **Quota**: unlimited, but subject to usage fees -* **Region**: world -* **SSL support**: no -* **Languages**: en, fr, de, it, es, pt, nl, zh, ja, ko -* **Documentation**: http://developer.yahoo.com/boss/geo/docs/index.html -* **Terms of Service**: http://info.yahoo.com/legal/us/yahoo/boss/tou/?pir=ucJPcJ1ibUn.h.d.lVmlcbcEkoHjwJ_PvxG9SLK9VIbIQAw1XFrnDqY- -* **Limitations**: No mass downloads, no commercial map production based on the data, no storage of data except for caching. - #### Bing (`:bing`) * **API key**: required (set `Geocoder.configure(:lookup => :bing, :api_key => key)`) @@ -784,6 +771,16 @@ This uses the PostcodeAnywhere UK Geocode service, this will geocode any string * **Documentation**: http://ipinfo.io/developers * **Terms of Service**: http://ipinfo.io/developers +#### IP-API.com (`:ipapi_com`) + +* **API key**: optional - see http://ip-api.com/docs/#usage_limits +* **Quota**: 150/minute - unlimited with api key +* **Region**: world +* **SSL support**: no (not without access key - see https://signup.ip-api.com/) +* **Languages**: English +* **Documentation**: http://ip-api.com/docs/ +* **Terms of Service**: https://signup.ip-api.com/terms + ### IP Address Local Database Services #### MaxMind Local (`:maxmind_local`) - EXPERIMENTAL @@ -1128,6 +1125,16 @@ A lot of debugging time can be saved by understanding how Geocoder works with Ac * using the `pluck` method (selects only a single column) * specifying another model through `includes` (selects columns from other tables) +### Geocoding is Slow + +With most lookups, addresses are translated into coordinates via an API that must be accessed through the Internet. These requests are subject to the same bandwidth constraints as every other HTTP request, and will vary in speed depending on network conditions. Furthermore, many of the services supported by Geocoder are free and thus very popular. Often they cannot keep up with demand and their response times become quite bad. + +If your application requires quick geocoding responses you will probably need to pay for a non-free service, or--if you're doing IP address geocoding--use a lookup that doesn't require an external (network-accessed) service. + +For IP address lookups in Rails applications, it is generally NOT a good idea to run `request.location` during a synchronous page load without understanding the speed/behavior of your configured lookup. If the lookup becomes slow, so will your website. + +For the most part, the speed of geocoding requests has little to do with the Geocoder gem. Please take the time to learn about your configured lookup (links to documentation are provided above) before posting performance-related issues. + ### Unexpected Responses from Geocoding Services Take a look at the server's raw response. You can do this by getting the request URL in an app console: diff --git a/lib/geocoder/configuration.rb b/lib/geocoder/configuration.rb index 6206e3a7ee5537a97f44bdce8c7dac2ab07194c9..7e96e8aab15a9105c6d8af0ddfa9cf6478973f53 100644 --- a/lib/geocoder/configuration.rb +++ b/lib/geocoder/configuration.rb @@ -17,10 +17,6 @@ module Geocoder if !options.nil? Configuration.instance.configure(options) end - - if config.lookup == :yahoo - Geocoder.log(:warn, "Yahoo BOSS Placefinder API will be discontinued March 31, 2016.") - end end ## diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb index 35ebc15e36ee31d969f6dba4106997656c9f740a..fdc4a0705b09020079320b1e25fb3ffea3ffb3db 100644 --- a/lib/geocoder/lookup.rb +++ b/lib/geocoder/lookup.rb @@ -28,7 +28,6 @@ module Geocoder :google, :google_premier, :google_places_details, - :yahoo, :bing, :geocoder_ca, :geocoder_us, @@ -65,7 +64,8 @@ module Geocoder :telize, :pointpin, :maxmind_geoip2, - :ipinfo_io + :ipinfo_io, + :ipapi_com ] end diff --git a/lib/geocoder/lookups/ipapi_com.rb b/lib/geocoder/lookups/ipapi_com.rb new file mode 100644 index 0000000000000000000000000000000000000000..df6f098b4182da3b7b7ac5b5235ba9fe19781b74 --- /dev/null +++ b/lib/geocoder/lookups/ipapi_com.rb @@ -0,0 +1,64 @@ +require 'geocoder/lookups/base' +require 'geocoder/results/ipapi_com' + +module Geocoder::Lookup + class IpapiCom < Base + + def name + "ip-api.com" + end + + def query_url(query) + url_ = "#{protocol}://ip-api.com/json/#{query.sanitized_text}" + + if (params = url_query_string(query)) && !params.empty? + url_ + "?" + params + else + url_ + end + end + + def supported_protocols + if configuration.api_key + [:http, :https] + else + [:http] + end + end + + + private + + def results(query) + return [reserved_result(query.text)] if query.loopback_ip_address? + + (doc = fetch_data(query)) ? [doc] : [] + end + + def reserved_result(query) + { + "message" => "reserved range", + "query" => query, + "status" => fail, + "ip" => query, + "city" => "", + "region_code" => "", + "region_name" => "", + "metrocode" => "", + "zipcode" => "", + "latitude" => "0", + "longitude" => "0", + "country_name" => "Reserved", + "country_code" => "RD" + } + end + + def query_url_params(query) + params = {} + params.merge!(fields: configuration[:fields]) if configuration.has_key?(:fields) + params.merge!(key: configuration.api_key) if configuration.api_key + params.merge(super) + end + + end +end diff --git a/lib/geocoder/lookups/yahoo.rb b/lib/geocoder/lookups/yahoo.rb deleted file mode 100644 index bf9fbec71daddc7e49fd21e8b97174fb56f97143..0000000000000000000000000000000000000000 --- a/lib/geocoder/lookups/yahoo.rb +++ /dev/null @@ -1,89 +0,0 @@ -require 'geocoder/lookups/base' -require "geocoder/results/yahoo" -require 'oauth_util' - -module Geocoder::Lookup - class Yahoo < Base - - def name - "Yahoo BOSS" - end - - def map_link_url(coordinates) - "http://maps.yahoo.com/#lat=#{coordinates[0]}&lon=#{coordinates[1]}" - end - - def required_api_key_parts - ["consumer key", "consumer secret"] - end - - def query_url(query) - parsed_url = URI.parse(raw_url(query)) - o = OauthUtil.new - o.consumer_key = configuration.api_key[0] - o.consumer_secret = configuration.api_key[1] - base_url + o.sign(parsed_url).query_string - end - - private # --------------------------------------------------------------- - - def results(query) - Geocoder.log(:warn, "Yahoo BOSS Placefinder API will be discontinued March 31, 2016.") - return [] unless doc = fetch_data(query) - doc = doc['bossresponse'] - if doc['responsecode'].to_i == 200 - if doc['placefinder']['count'].to_i > 0 - return doc['placefinder']['results'] - else - return [] - end - else - Geocoder.log(:warn, "Yahoo Geocoding API error: #{doc['responsecode']} (#{doc['reason']}).") - return [] - end - end - - ## - # Yahoo returns errors as XML even when JSON format is specified. - # Handle that here, without parsing the XML - # (which would add unnecessary complexity). - # Yahoo auth errors can also be cryptic, so add raw error desc - # to warning message. - # - def parse_raw_data(raw_data) - if raw_data.match(/^<\?xml/) - if raw_data.include?("Rate Limit Exceeded") - raise_error(Geocoder::OverQueryLimitError) || Geocoder.log(:warn, "Over API query limit.") - elsif raw_data =~ /<yahoo:description>(Please provide valid credentials.*)<\/yahoo:description>/i - raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid API key. Error response: #{$1}") - end - else - super(raw_data) - end - end - - def query_url_params(query) - lang = (query.language || configuration.language).to_s - lang += '_US' if lang == 'en' - { - :location => query.sanitized_text, - :flags => "JXTSR", - :gflags => "AC#{'R' if query.reverse_geocode?}", - :locale => lang, - :appid => configuration.api_key - }.merge(super) - end - - def cache_key(query) - raw_url(query) - end - - def base_url - "#{protocol}://yboss.yahooapis.com/geo/placefinder?" - end - - def raw_url(query) - base_url + url_query_string(query) - end - end -end diff --git a/lib/geocoder/results/ipapi_com.rb b/lib/geocoder/results/ipapi_com.rb new file mode 100644 index 0000000000000000000000000000000000000000..0ac3264868646879ca937306a2db67651472e764 --- /dev/null +++ b/lib/geocoder/results/ipapi_com.rb @@ -0,0 +1,53 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class IpapiCom < Base + + def latitude + lat + end + + def longitude + lon + end + + def coordinates + [lat, lon] + end + + def address + "#{city}, #{state_code} #{postal_code}, #{country}".sub(/^[ ,]*/, "") + end + + def state + region_name + end + + def state_code + region + end + + def postal_code + zip + end + + def country_code + @data['countryCode'] + end + + def region_name + @data['regionName'] + end + + def self.response_attributes + %w[country region city zip timezone isp org as reverse query status message mobile proxy lat lon] + end + + response_attributes.each do |attribute| + define_method attribute do + @data[attribute] + end + end + + end +end diff --git a/lib/geocoder/results/yahoo.rb b/lib/geocoder/results/yahoo.rb deleted file mode 100644 index e5b7b5642e6435d0b6bc4ce6896a734d1e955f1e..0000000000000000000000000000000000000000 --- a/lib/geocoder/results/yahoo.rb +++ /dev/null @@ -1,60 +0,0 @@ -require 'geocoder/results/base' - -module Geocoder::Result - class Yahoo < Base - - def address(format = :full) - (1..4).to_a.map{ |i| @data["line#{i}"] }.reject{ |i| i.nil? or i == "" }.join(", ") - end - - def city - @data['city'] - end - - def state - @data['state'] - end - - def state_code - @data['statecode'] - end - - def country - @data['country'] - end - - def country_code - @data['countrycode'] - end - - def postal_code - @data['postal'] - end - - def address_hash - @data['hash'] - end - - def viewport - boundingbox = @data['boundingbox'] || fail - %w(south west north east).map{ |i| boundingbox[i].to_f } - end - - def self.response_attributes - %w[quality offsetlat offsetlon radius boundingbox name - line1 line2 line3 line4 cross house street xstreet unittype unit - city state statecode country countrycode postal - neighborhood county countycode - level0 level1 level2 level3 level4 level0code level1code level2code - timezone areacode uzip hash woeid woetype] - end - - response_attributes.each do |a| - unless method_defined?(a) - define_method a do - @data[a] - end - end - end - end -end diff --git a/lib/geocoder/version.rb b/lib/geocoder/version.rb index 77eb47f0d15f52e3aa0dbd03d0aec6a4b025e162..b50a353b7bb21ce69ca8b7007837cd76ead2d23b 100644 --- a/lib/geocoder/version.rb +++ b/lib/geocoder/version.rb @@ -1,3 +1,3 @@ module Geocoder - VERSION = "1.3.1" + VERSION = "1.3.3" end diff --git a/lib/oauth_util.rb b/lib/oauth_util.rb deleted file mode 100644 index 7299b5f28222a8b38eb6b89a1c2a74236c7a5323..0000000000000000000000000000000000000000 --- a/lib/oauth_util.rb +++ /dev/null @@ -1,112 +0,0 @@ -# A utility for signing an url using OAuth in a way that's convenient for debugging -# Note: the standard Ruby OAuth lib is here http://github.com/mojodna/oauth -# Source: http://gist.github.com/383159 -# License: http://gist.github.com/375593 -# Usage: see example.rb below -# -# NOTE: This file has been modified from the original Gist: -# -# 1. Fix to prevent param-array conversion, as mentioned in Gist comment. -# 2. Query string escaping has been changed. See: -# https://github.com/alexreisner/geocoder/pull/360 -# - -require 'uri' -require 'cgi' -require 'openssl' -require 'base64' - -class OauthUtil - - attr_accessor :consumer_key, :consumer_secret, :token, :token_secret, :req_method, - :sig_method, :oauth_version, :callback_url, :params, :req_url, :base_str - - def initialize - @consumer_key = '' - @consumer_secret = '' - @token = '' - @token_secret = '' - @req_method = 'GET' - @sig_method = 'HMAC-SHA1' - @oauth_version = '1.0' - @callback_url = '' - end - - # openssl::random_bytes returns non-word chars, which need to be removed. using alt method to get length - # ref http://snippets.dzone.com/posts/show/491 - def nonce - Array.new( 5 ) { rand(256) }.pack('C*').unpack('H*').first - end - - def percent_encode( string ) - - # ref http://snippets.dzone.com/posts/show/1260 - return URI.escape( string, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") ).gsub('*', '%2A') - end - - # @ref http://oauth.net/core/1.0/#rfc.section.9.2 - def signature - key = percent_encode( @consumer_secret ) + '&' + percent_encode( @token_secret ) - - # ref: http://blog.nathanielbibler.com/post/63031273/openssl-hmac-vs-ruby-hmac-benchmarks - digest = OpenSSL::Digest.new( 'sha1' ) - hmac = OpenSSL::HMAC.digest( digest, key, @base_str ) - - # ref http://groups.google.com/group/oauth-ruby/browse_thread/thread/9110ed8c8f3cae81 - Base64.encode64( hmac ).chomp.gsub( /\n/, '' ) - end - - # sort (very important as it affects the signature), concat, and percent encode - # @ref http://oauth.net/core/1.0/#rfc.section.9.1.1 - # @ref http://oauth.net/core/1.0/#9.2.1 - # @ref http://oauth.net/core/1.0/#rfc.section.A.5.1 - def query_string - pairs = [] - @params.sort.each { | key, val | - pairs.push( "#{ CGI.escape(key.to_s).gsub(/%(5B|5D)/n) { [$1].pack('H*') } }=#{ CGI.escape(val.to_s) }" ) - } - pairs.join '&' - end - - # organize params & create signature - def sign( parsed_url ) - - @params = { - 'oauth_consumer_key' => @consumer_key, - 'oauth_nonce' => nonce, - 'oauth_signature_method' => @sig_method, - 'oauth_timestamp' => Time.now.to_i.to_s, - 'oauth_version' => @oauth_version - } - - # if url has query, merge key/values into params obj overwriting defaults - if parsed_url.query - CGI.parse( parsed_url.query ).each do |k,v| - if v.is_a?(Array) && v.count == 1 - @params[k] = v.first - else - @params[k] = v - end - end - end - - # @ref http://oauth.net/core/1.0/#rfc.section.9.1.2 - @req_url = parsed_url.scheme + '://' + parsed_url.host + parsed_url.path - - # create base str. make it an object attr for ez debugging - # ref http://oauth.net/core/1.0/#anchor14 - @base_str = [ - @req_method, - percent_encode( req_url ), - - # normalization is just x-www-form-urlencoded - percent_encode( query_string ) - - ].join( '&' ) - - # add signature - @params[ 'oauth_signature' ] = signature - - return self - end -end diff --git a/test/fixtures/ipapi_com_74_200_247_59 b/test/fixtures/ipapi_com_74_200_247_59 new file mode 100644 index 0000000000000000000000000000000000000000..5304304721bf7fd917a3b54072a77182b2f5634f --- /dev/null +++ b/test/fixtures/ipapi_com_74_200_247_59 @@ -0,0 +1,19 @@ +{ + "as": "AS22576 DataPipe, Inc.", + "city": "Jersey City", + "country": "United States", + "countryCode": "US", + "isp": "DataPipe", + "lat": 40.7209, + "lon": -74.0468, + "mobile": false, + "org": "DataPipe", + "proxy": false, + "query": "74.200.247.59", + "region": "NJ", + "regionName": "New Jersey", + "reverse": "", + "status": "success", + "timezone": "America/New_York", + "zip": "07302" +} diff --git a/test/fixtures/ipapi_com_no_results b/test/fixtures/ipapi_com_no_results new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/test/fixtures/yahoo_error b/test/fixtures/yahoo_error deleted file mode 100644 index 7dbfdfeabeaa611d00af6ef756118795619703a1..0000000000000000000000000000000000000000 --- a/test/fixtures/yahoo_error +++ /dev/null @@ -1 +0,0 @@ -{"bossresponse":{"responsecode":"6000","reason":"internal error"}} diff --git a/test/fixtures/yahoo_invalid_key b/test/fixtures/yahoo_invalid_key deleted file mode 100644 index c9b7319b05361287a7829d884d051fb397f36e4d..0000000000000000000000000000000000000000 --- a/test/fixtures/yahoo_invalid_key +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version='1.0' encoding='UTF-8'?>\n<yahoo:error xmlns:yahoo='http://yahooapis.com/v1/base.rng'\n xml:lang='en-US'> - <yahoo:description>Please provide valid credentials. OAuth oauth_problem="consumer_key_unknown", realm="yahooapis.com"</yahoo:description>\n</yahoo:error> diff --git a/test/fixtures/yahoo_madison_square_garden b/test/fixtures/yahoo_madison_square_garden deleted file mode 100644 index 24161f60b57f58f99c68ec9e99f648c89ee08097..0000000000000000000000000000000000000000 --- a/test/fixtures/yahoo_madison_square_garden +++ /dev/null @@ -1,52 +0,0 @@ -{ - "bossresponse": { - "responsecode": "200", - "placefinder": { - "start": "0", - "count": "1", - "request": "flags=JXTSR&location=Madison%20Square%20Garden%2C%20NY%2C%20NY&%unsafe%appid=%5B%22dj0yJmk9ZmZ5NXFrNGhNcEthJmQ9WVdrOVFUSlhPV2x1TjJVbWNHbzlORE0wT0RFME9UWXkmcz1jb25zdW1lcnNlY3JldCZ4PTAy%22%2C%20%22b57b1b98eb21f171231f5b441cba505261d6c9bb%22%5D&gflags=AC&locale=en_US", - "results": [ - { - "quality": "90", - "latitude": "40.750381", - "longitude": "-73.993988", - "offsetlat": "40.750381", - "offsetlon": "-73.993988", - "radius": "400", - "boundingbox": { - "north": "40.750832", - "south": "40.749931", - "east": "-73.993393", - "west": "-73.994591" - }, - "name": "Madison Square Garden", - "line1": "Madison Square Garden", - "line2": "New York, NY 10001", - "line3": "", - "line4": "United States", - "cross": "", - "house": "", - "street": "", - "xstreet": "", - "unittype": "", - "unit": "", - "postal": "10001", - "neighborhood": "Garment District|Midtown|Midtown West|Manhattan", - "city": "New York", - "county": "New York County", - "state": "New York", - "country": "United States", - "countrycode": "US", - "statecode": "NY", - "countycode": "", - "timezone": "America/New_York", - "areacode": "212", - "uzip": "10001", - "hash": "", - "woeid": "23617041", - "woetype": "20" - } - ] - } - } -} diff --git a/test/fixtures/yahoo_no_results b/test/fixtures/yahoo_no_results deleted file mode 100644 index 0c65fddc4a9dd4aa3791c7ec19ef75ba977837e8..0000000000000000000000000000000000000000 --- a/test/fixtures/yahoo_no_results +++ /dev/null @@ -1,10 +0,0 @@ -{ - "bossresponse": { - "responsecode": "200", - "placefinder": { - "start": "0", - "count": "0", - "request": "flags=JXTSR&location=asdfasdf28394782sdfj2983&%unsafe%appid=%5B%22dj0yJmk9ZmZ5NXFrNGhNcEthJmQ9WVdrOVFUSlhPV2x1TjJVbWNHbzlORE0wT0RFME9UWXkmcz1jb25zdW1lcnNlY3JldCZ4PTAy%22%2C%20%22b57b1b98eb21f171231f5b441cba505261d6c9bb%22%5D&gflags=AC&locale=en_US" - } - } -} diff --git a/test/fixtures/yahoo_over_limit b/test/fixtures/yahoo_over_limit deleted file mode 100644 index 7dddadf5f0d5e75bae7fd245d34dac41012e23aa..0000000000000000000000000000000000000000 --- a/test/fixtures/yahoo_over_limit +++ /dev/null @@ -1,2 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> <yahoo:error xmlns:yahoo="http://yahooapis.com/v1/base.rng\ <http://yahooapis.com/v1/base.rng%5C>" xml:lang="en-US"> - <yahoo:description>Rate Limit Exceeded</yahoo:description> <yahoo:detail>Key has exceeded its configured rate limit.</yahoo:detail> </yahoo:error> diff --git a/test/test_helper.rb b/test/test_helper.rb index 4a9c4d62c1fe549b51ef1865312d46cd02ffe939..8ad22fc798c4f541acfeab13b8540fe72fba2bff 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -336,6 +336,14 @@ module Geocoder end end + require 'geocoder/lookups/ipapi_com' + class IpapiCom + private + def default_fixture_filename + "ipapi_com_74_200_247_59" + end + end + end end diff --git a/test/unit/logger_test.rb b/test/unit/logger_test.rb index 01efefa117f332281d597d82393b4f601035fda1..c018ee12ac39eb3d5464155735d7d3002e83b976 100644 --- a/test/unit/logger_test.rb +++ b/test/unit/logger_test.rb @@ -18,7 +18,7 @@ class LoggerTest < GeocoderTestCase def test_set_logger_logs assert_equal nil, Geocoder.log(:warn, "should log") - assert_match /should log\n$/, @tempfile.read + assert_match(/should log\n$/, @tempfile.read) end def test_logger_does_not_log_severity_too_low @@ -30,7 +30,7 @@ class LoggerTest < GeocoderTestCase def test_logger_logs_when_severity_high_enough @logger.level = Logger::DEBUG Geocoder.log(:warn, "important: should log!") - assert_match /important: should log/, @tempfile.read + assert_match(/important: should log/, @tempfile.read) end def test_kernel_logger_does_not_log_severity_too_low diff --git a/test/unit/lookup_test.rb b/test/unit/lookup_test.rb index bf7903c33b54dc319ab6c5e8ec2a64f229e54b8b..5a91ad573596da1fbf2a8acda5b3772ff882a721 100644 --- a/test/unit/lookup_test.rb +++ b/test/unit/lookup_test.rb @@ -24,13 +24,12 @@ 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, :ipinfo_io].include? l # does not use query string + next if [:freegeoip, :maxmind_local, :telize, :pointpin, :geoip2, :maxmind_geoip2, :mapbox, :ipinfo_io, :ipapi_com].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"} )) - # should be "+"s for all lookups except Yahoo - assert_match(/one_in_the_hand=two(%20|\+)in(%20|\+)the(%20|\+)bush/, url, + assert_match(/one_in_the_hand=two\+in\+the\+bush/, url, "Lookup #{l} does not appear to support arbitrary params in URL") end end @@ -44,7 +43,6 @@ class LookupTest < GeocoderTestCase :mapquest => :key, :maxmind => :l, :nominatim => :"accept-language", - :yahoo => :locale, :yandex => :plng }.each do |l,p| define_method "test_passing_param_to_#{l}_query_overrides_configuration_value" do @@ -61,7 +59,6 @@ class LookupTest < GeocoderTestCase :google => :language, :google_premier => :language, :nominatim => :"accept-language", - :yahoo => :locale, :yandex => :plng }.each do |l,p| define_method "test_passing_language_to_#{l}_query_overrides_configuration_value" do @@ -77,7 +74,7 @@ class LookupTest < GeocoderTestCase def test_raises_exception_on_invalid_key Geocoder.configure(:always_raise => [Geocoder::InvalidApiKey]) #Geocoder::Lookup.all_services_except_test.each do |l| - [:bing, :yahoo, :yandex, :maxmind, :baidu, :baidu_ip].each do |l| + [:bing, :yandex, :maxmind, :baidu, :baidu_ip].each do |l| lookup = Geocoder::Lookup.get(l) assert_raises Geocoder::InvalidApiKey do lookup.send(:results, Geocoder::Query.new("invalid key")) @@ -88,7 +85,7 @@ class LookupTest < GeocoderTestCase def test_returns_empty_array_on_invalid_key silence_warnings do #Geocoder::Lookup.all_services_except_test.each do |l| - [:bing, :yahoo, :yandex, :maxmind, :baidu, :baidu_ip].each do |l| + [:bing, :yandex, :maxmind, :baidu, :baidu_ip].each do |l| Geocoder.configure(:lookup => l) set_api_key!(l) assert_equal [], Geocoder.search("invalid key") diff --git a/test/unit/lookups/geocodio_test.rb b/test/unit/lookups/geocodio_test.rb index 43e44f4b9305e8513a6c3ec4cd523640e9b2b899..6b316be9825d9e726e87d9f7f9dd28664bb50082 100644 --- a/test/unit/lookups/geocodio_test.rb +++ b/test/unit/lookups/geocodio_test.rb @@ -29,7 +29,7 @@ class GeocodioTest < GeocoderTestCase def test_geocodio_reverse_url query = Geocoder::Query.new([45.423733, -75.676333]) - assert_match /reverse/, query.url + assert_match(/reverse/, query.url) end def test_raises_invalid_request_exception diff --git a/test/unit/lookups/geoip2_test.rb b/test/unit/lookups/geoip2_test.rb index 46f2b476112e0cf30d46e4d8ad2a64affcbb7a17..d50e3bce67e866355c46cf1ad9bab126c7042745 100644 --- a/test/unit/lookups/geoip2_test.rb +++ b/test/unit/lookups/geoip2_test.rb @@ -20,7 +20,7 @@ class Geoip2Test < GeocoderTestCase assert_equal 'US', result.country_code assert_equal '94043', result.postal_code assert_equal 37.41919999999999, result.latitude - assert_equal -122.0574, result.longitude + assert_equal(-122.0574, result.longitude) assert_equal [37.41919999999999, -122.0574], result.coordinates end diff --git a/test/unit/lookups/google_test.rb b/test/unit/lookups/google_test.rb index 867508e1901237812804abc2ceefc7aef7e4f059..d658a82745c980de185d4dfca0ffded0b3adc2e5 100644 --- a/test/unit/lookups/google_test.rb +++ b/test/unit/lookups/google_test.rb @@ -89,6 +89,6 @@ class GoogleTest < GeocoderTestCase def test_google_uses_https_when_api_key_is_set Geocoder.configure(api_key: "deadbeef") query = Geocoder::Query.new("Madison Square Garden, New York, NY") - assert_match /^https:/, query.url + assert_match(/^https:/, query.url) end end diff --git a/test/unit/lookups/ipapi_com_test.rb b/test/unit/lookups/ipapi_com_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..6cb07cb9545cd98ff4433872837030351ac9a311 --- /dev/null +++ b/test/unit/lookups/ipapi_com_test.rb @@ -0,0 +1,73 @@ +# encoding: utf-8 +require 'test_helper' + +class IpapiComTest < GeocoderTestCase + + def setup + Geocoder::Configuration.instance.data.clear + Geocoder::Configuration.set_defaults + Geocoder.configure(ip_lookup: :ipapi_com) + end + + def test_result_on_ip_address_search + result = Geocoder.search("74.200.247.59").first + assert result.is_a?(Geocoder::Result::IpapiCom) + end + + def test_result_components + result = Geocoder.search("74.200.247.59").first + assert_equal "Jersey City, NJ 07302, United States", result.address + end + + def test_all_api_fields + result = Geocoder.search("74.200.247.59").first + assert_equal "United States", result.country + assert_equal "US", result.country_code + assert_equal "NJ", result.region + assert_equal "New Jersey", result.region_name + assert_equal "Jersey City", result.city + assert_equal "07302", result.zip + assert_equal 40.7209, result.lat + assert_equal -74.0468, result.lon + assert_equal "America/New_York", result.timezone + assert_equal "DataPipe", result.isp + assert_equal "DataPipe", result.org + assert_equal "AS22576 DataPipe, Inc.", result.as + assert_equal "", result.reverse + assert_equal false, result.mobile + assert_equal false, result.proxy + assert_equal "74.200.247.59", result.query + assert_equal "success", result.status + assert_equal nil, result.message + end + + def test_api_key + Geocoder.configure(:api_key => "MY_KEY") + g = Geocoder::Lookup::IpapiCom.new + assert_match "key=MY_KEY", g.query_url(Geocoder::Query.new("74.200.247.59")) + end + + def test_url_with_api_key_and_fields + Geocoder.configure(:api_key => "MY_KEY", :ipapi_com => {:fields => "lat,lon,xyz"}) + g = Geocoder::Lookup::IpapiCom.new + assert_equal "http://ip-api.com/json/74.200.247.59?fields=lat%2Clon%2Cxyz&key=MY_KEY", g.query_url(Geocoder::Query.new("74.200.247.59")) + end + + def test_url_with_fields + Geocoder.configure(:ipapi_com => {:fields => "lat,lon"}) + g = Geocoder::Lookup::IpapiCom.new + assert_equal "http://ip-api.com/json/74.200.247.59?fields=lat%2Clon", g.query_url(Geocoder::Query.new("74.200.247.59")) + end + + def test_url_without_fields + g = Geocoder::Lookup::IpapiCom.new + assert_equal "http://ip-api.com/json/74.200.247.59", g.query_url(Geocoder::Query.new("74.200.247.59")) + end + + def test_search_with_params + g = Geocoder::Lookup::IpapiCom.new + q = Geocoder::Query.new("74.200.247.59", :params => {:fields => 'lat,zip'}) + assert_equal "http://ip-api.com/json/74.200.247.59?fields=lat%2Czip", g.query_url(q) + end + +end diff --git a/test/unit/lookups/ipinfo_io_test.rb b/test/unit/lookups/ipinfo_io_test.rb index 4c3eccdecdb6c635b20d4611dc654212fbd5e119..379f383814a7659b261b76facc4264219d1d8acd 100644 --- a/test/unit/lookups/ipinfo_io_test.rb +++ b/test/unit/lookups/ipinfo_io_test.rb @@ -6,12 +6,12 @@ class IpinfoIoTest < GeocoderTestCase def test_ipinfo_io_use_http_without_token Geocoder.configure(:ip_lookup => :ipinfo_io, :use_https => true) query = Geocoder::Query.new("8.8.8.8") - assert_match /^http:/, query.url + assert_match(/^http:/, query.url) end def test_ipinfo_io_uses_https_when_auth_token_set Geocoder.configure(:ip_lookup => :ipinfo_io, :api_key => "FOO_BAR_TOKEN", :use_https => true) query = Geocoder::Query.new("8.8.8.8") - assert_match /^https:/, query.url + assert_match(/^https:/, query.url) end end diff --git a/test/unit/lookups/latlon_test.rb b/test/unit/lookups/latlon_test.rb index 2dcb47a9bbe289d66f38b44d0992428726d88bd1..49ca664297001a0cdfc74ab42010dd01a6458fab 100644 --- a/test/unit/lookups/latlon_test.rb +++ b/test/unit/lookups/latlon_test.rb @@ -29,7 +29,7 @@ class LatlonTest < GeocoderTestCase def test_latlon_reverse_url query = Geocoder::Query.new([45.423733, -75.676333]) - assert_match /reverse_geocode/, query.url + assert_match(/reverse_geocode/, query.url) end def test_raises_api_key_exception diff --git a/test/unit/lookups/maxmind_geoip2_test.rb b/test/unit/lookups/maxmind_geoip2_test.rb index 35235cbcf851ed44a632c4d60ddf260757a7dc28..a930a20137010f078e3e2060a611a2a132cedfaf 100644 --- a/test/unit/lookups/maxmind_geoip2_test.rb +++ b/test/unit/lookups/maxmind_geoip2_test.rb @@ -15,8 +15,8 @@ class MaxmindGeoip2Test < GeocoderTestCase assert_equal 'United States', result.country assert_equal 'US', result.country_code assert_equal '90001', result.postal_code - assert_equal 37.6293, result.latitude - assert_equal -122.1163, result.longitude + assert_equal(37.6293, result.latitude) + assert_equal(-122.1163, result.longitude) assert_equal [37.6293, -122.1163], result.coordinates end diff --git a/test/unit/lookups/maxmind_local_test.rb b/test/unit/lookups/maxmind_local_test.rb index b5bf847c4585d5c35fca3e8e89d50bb5d3af4b5f..87b494814cab6e8b492769cc30d66cfb4d9876f4 100644 --- a/test/unit/lookups/maxmind_local_test.rb +++ b/test/unit/lookups/maxmind_local_test.rb @@ -15,8 +15,8 @@ class MaxmindLocalTest < GeocoderTestCase assert_equal 'United States', result.country assert_equal 'US', result.country_code assert_equal '94043', result.postal_code - assert_equal 37.41919999999999, result.latitude - assert_equal -122.0574, result.longitude + assert_equal(37.41919999999999, result.latitude) + assert_equal(-122.0574, result.longitude) assert_equal [37.41919999999999, -122.0574], result.coordinates end diff --git a/test/unit/lookups/opencagedata_test.rb b/test/unit/lookups/opencagedata_test.rb index 3e838b657bc0c42378419ffd7241afc03687ae2b..496ec14a5220e6d6f3051b7e6e1f25836b978529 100644 --- a/test/unit/lookups/opencagedata_test.rb +++ b/test/unit/lookups/opencagedata_test.rb @@ -11,7 +11,7 @@ class OpencagedataTest < GeocoderTestCase 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 + assert_match(/46, West 31st Street, Koreatown, New York County, 10011, New York City, New York, United States of America/, result.address) end @@ -39,7 +39,7 @@ class OpencagedataTest < GeocoderTestCase def test_opencagedata_reverse_url query = Geocoder::Query.new([45.423733, -75.676333]) - assert_match /\bq=45.423733%2C-75.676333\b/, query.url + assert_match(/\bq=45.423733%2C-75.676333\b/, query.url) end diff --git a/test/unit/lookups/smarty_streets_test.rb b/test/unit/lookups/smarty_streets_test.rb index 7e999a6c1fe2c9bdf84a8f90b60b859a41257bb7..04e19c43516587b09469b92e2a617e24c6c3717b 100644 --- a/test/unit/lookups/smarty_streets_test.rb +++ b/test/unit/lookups/smarty_streets_test.rb @@ -11,22 +11,22 @@ class SmartyStreetsTest < GeocoderTestCase def test_url_contains_api_key Geocoder.configure(:smarty_streets => {:api_key => 'blah'}) query = Geocoder::Query.new("Bluffton, SC") - assert_match /auth-token=blah/, query.url + assert_match(/auth-token=blah/, query.url) end def test_query_for_address_geocode query = Geocoder::Query.new("42 Wallaby Way Sydney, AU") - assert_match /api\.smartystreets\.com\/street-address\?/, query.url + assert_match(/api\.smartystreets\.com\/street-address\?/, query.url) end def test_query_for_zipcode_geocode query = Geocoder::Query.new("22204") - assert_match /api\.smartystreets\.com\/zipcode\?/, query.url + assert_match(/api\.smartystreets\.com\/zipcode\?/, query.url) end def test_query_for_zipfour_geocode query = Geocoder::Query.new("22204-1603") - assert_match /api\.smartystreets\.com\/zipcode\?/, query.url + assert_match(/api\.smartystreets\.com\/zipcode\?/, query.url) end def test_smarty_streets_result_components diff --git a/test/unit/lookups/yahoo_test.rb b/test/unit/lookups/yahoo_test.rb deleted file mode 100644 index 3289bb4b25e3da0889760d0d06183cf1cafcec33..0000000000000000000000000000000000000000 --- a/test/unit/lookups/yahoo_test.rb +++ /dev/null @@ -1,40 +0,0 @@ -# encoding: utf-8 -require 'test_helper' - -class YahooTest < GeocoderTestCase - - def setup - Geocoder.configure(lookup: :yahoo) - set_api_key!(:yahoo) - end - - def test_no_results - assert_equal [], Geocoder.search("no results") - end - - def test_error - silence_warnings do - assert_equal [], Geocoder.search("error") - end - end - - def test_result_components - result = Geocoder.search("madison square garden").first - assert_equal "10001", result.postal_code - assert_equal "Madison Square Garden, New York, NY 10001, United States", result.address - end - - def test_result_viewport - result = Geocoder.search("Madison Square Garden, New York, NY").first - assert_equal [40.749931, -73.994591, 40.750832, -73.993393], - result.viewport - end - - def test_raises_exception_when_over_query_limit - Geocoder.configure(:always_raise => [Geocoder::OverQueryLimitError]) - l = Geocoder::Lookup.get(:yahoo) - assert_raises Geocoder::OverQueryLimitError do - l.send(:results, Geocoder::Query.new("over limit")) - end - end -end diff --git a/test/unit/oauth_util_test.rb b/test/unit/oauth_util_test.rb deleted file mode 100644 index 78763f8ef98c4e83c3942247b4d1a6553cd24fd5..0000000000000000000000000000000000000000 --- a/test/unit/oauth_util_test.rb +++ /dev/null @@ -1,30 +0,0 @@ -# encoding: utf-8 -require 'test_helper' -require 'cgi' -require 'uri' - -class OauthUtilTest < GeocoderTestCase - def test_query_string_escapes_single_quote - base_url = "http://example.com?location=d'iberville" - - o = OauthUtil.new - o.consumer_key = 'consumer_key' - o.consumer_secret = 'consumer_secret' - - query_string = o.sign(URI.parse(base_url)).query_string - - assert_match "location=d%27iberville", query_string - end - - def test_query_string_sorts_url_keys - base_url = "http://example.com?a_param=a&z_param=b&b_param=c&n_param=d" - - o = OauthUtil.new - o.consumer_key = 'consumer_key' - o.consumer_secret = 'consumer_secret' - - query_string = o.sign(URI.parse(base_url)).query_string - - assert_match(/.*a_param=.*b_param=.*n_param=.*z_param=.*/, query_string) - end -end