diff --git a/lib/geocoder.rb b/lib/geocoder.rb index 4deeeea5c933e49688f0031a237a98a4a52b45e5..731a17f671680c68f647391e2abb54e8271f9161 100644 --- a/lib/geocoder.rb +++ b/lib/geocoder.rb @@ -82,7 +82,7 @@ module Geocoder # dot-delimited 8-bit numbers. # def ip_address?(value) - value.match /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ + !!value.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) end ## diff --git a/lib/geocoder/lookups/base.rb b/lib/geocoder/lookups/base.rb index 8b2ddd11dd7ec1c0679862829bb0e54d7573d5b5..3d8c66febd4c514153b74ad9faf780ea8abfa98a 100644 --- a/lib/geocoder/lookups/base.rb +++ b/lib/geocoder/lookups/base.rb @@ -88,6 +88,13 @@ module Geocoder end end + ## + # Is the given string a loopback IP address? + # + def loopback_address?(ip) + !!(ip == "0.0.0.0" or ip.match(/^127/)) + end + ## # Simulate ActiveSupport's Object#to_query. # diff --git a/lib/geocoder/lookups/freegeoip.rb b/lib/geocoder/lookups/freegeoip.rb index 791bac4c2d5b79091915541d55b01538c01c90e0..dcc5e44f5565ef97cb2d73228a78ab3c55a7af7f 100644 --- a/lib/geocoder/lookups/freegeoip.rb +++ b/lib/geocoder/lookups/freegeoip.rb @@ -7,6 +7,8 @@ module Geocoder::Lookup private # --------------------------------------------------------------- def result(query, reverse = false) + # don't look up a loopback address, just return the stored result + return reserved_result(query) if loopback_address?(query) begin if doc = fetch_data(query, reverse) doc @@ -16,6 +18,21 @@ module Geocoder::Lookup end end + def reserved_result(ip) + { + "ip" => ip, + "city" => "", + "region_code" => "", + "region_name" => "", + "metrocode" => "", + "zipcode" => "", + "latitude" => "0", + "longitude" => "0", + "country_name" => "Reserved", + "country_code" => "RD" + } + end + def query_url(query, reverse = false) "http://freegeoip.net/json/#{query}" end diff --git a/lib/geocoder/lookups/google.rb b/lib/geocoder/lookups/google.rb index ed263c9782a16da9d359067491ed5689d4ee44d2..88764dceea69be2e0e1de1523b432b1656a6b257 100644 --- a/lib/geocoder/lookups/google.rb +++ b/lib/geocoder/lookups/google.rb @@ -8,7 +8,7 @@ module Geocoder::Lookup def result(query, reverse = false) doc = fetch_data(query, reverse) - case doc['status']; when "OK" + case doc['status']; when "OK" # OK status implies >0 results doc['results'].first when "OVER_QUERY_LIMIT" warn "Google Geocoding API error: over query limit." diff --git a/lib/geocoder/lookups/yahoo.rb b/lib/geocoder/lookups/yahoo.rb index e8665fa0465515e13d7b3d7305472527b99ba6fd..3d8e112fa0e6da62991eaa86d16c9ff034fe3d8e 100644 --- a/lib/geocoder/lookups/yahoo.rb +++ b/lib/geocoder/lookups/yahoo.rb @@ -9,7 +9,7 @@ module Geocoder::Lookup def result(query, reverse = false) doc = fetch_data(query, reverse) if doc = doc['ResultSet'] and doc['Error'] == 0 - doc['Results'].first + doc['Results'].first if doc['Found'] > 0 else warn "Yahoo Geocoding API error: #{doc['Error']} (#{doc['ErrorMessage']})." end diff --git a/lib/geocoder/request.rb b/lib/geocoder/request.rb index e2b1a9c8db28c09083bc41cdbaadd870ef98aae9..cf3e6b3ad5d50ac58b520fcec0845e1f5ce356a3 100644 --- a/lib/geocoder/request.rb +++ b/lib/geocoder/request.rb @@ -1,16 +1,13 @@ require 'geocoder' -require 'geocoder/results/freegeoip' module Geocoder module Request def location - if ip.nil? or ip == "0.0.0.0" or ip.match /^127/ # don't look up loopback - # but return a Geocoder::Result for consistency - Geocoder::Result::Freegeoip.new("ip" => ip) - else - Geocoder.search(ip).first + unless defined?(@location) + @location = Geocoder.search(ip) end + @location end end end diff --git a/test/fixtures/google_no_results.json b/test/fixtures/google_no_results.json new file mode 100644 index 0000000000000000000000000000000000000000..afa9ac144c535650c2131bc54426c885f599f93e --- /dev/null +++ b/test/fixtures/google_no_results.json @@ -0,0 +1,4 @@ +{ + "status": "ZERO_RESULTS", + "results": [ ] +} diff --git a/test/fixtures/yahoo_no_results.json b/test/fixtures/yahoo_no_results.json new file mode 100644 index 0000000000000000000000000000000000000000..e97865dfcf60fb4e970caac77d2187f3eadf640d --- /dev/null +++ b/test/fixtures/yahoo_no_results.json @@ -0,0 +1,10 @@ +{ + "ResultSet":{ + "version":"1.0", + "Error":0, + "ErrorMessage":"No error", + "Locale":"us_US", + "Quality":10, + "Found":0 + } +} diff --git a/test/geocoder_test.rb b/test/geocoder_test.rb index b951ac8af71826c9ebd8b0a90ae38e59a2b606a2..f4a9b3ecfe0d8b973417e5c8fa20003fc6979249 100644 --- a/test/geocoder_test.rb +++ b/test/geocoder_test.rb @@ -108,6 +108,10 @@ class GeocoderTest < Test::Unit::TestCase assert_result_has_required_attributes(result) end + def test_google_returns_nil_when_no_results + assert_nil Geocoder.search("no results") + end + # --- Yahoo --- @@ -130,6 +134,11 @@ class GeocoderTest < Test::Unit::TestCase assert_result_has_required_attributes(result) end + def test_yahoo_returns_nil_when_no_results + Geocoder::Configuration.lookup = :yahoo + assert_nil Geocoder.search("no results") + end + # --- FreeGeoIp --- diff --git a/test/test_helper.rb b/test/test_helper.rb index 865ee7c252a2059190de5eeed9558c5549ec1e68..a283bb2db34731835bdf8de6dc4a7026aef423b4 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -50,14 +50,16 @@ module Geocoder class Google < Base private #----------------------------------------------------------------- def fetch_raw_data(query, reverse = false) - File.read(File.join("test", "fixtures", "google_madison_square_garden.json")) + file = query == "no results" ? :no_results : :madison_square_garden + File.read(File.join("test", "fixtures", "google_#{file}.json")) end end class Yahoo < Base private #----------------------------------------------------------------- def fetch_raw_data(query, reverse = false) - File.read(File.join("test", "fixtures", "yahoo_madison_square_garden.json")) + file = query == "no results" ? :no_results : :madison_square_garden + File.read(File.join("test", "fixtures", "yahoo_#{file}.json")) end end