Skip to content
Snippets Groups Projects
Commit fd5f7e09 authored by Alex Reisner's avatar Alex Reisner
Browse files

Add IP address geocoding.

parent 076a2ebd
No related branches found
No related tags found
No related merge requests found
......@@ -7,14 +7,16 @@ module Geocoder
extend self
##
# Alias for Geocoder.lookup.search.
# Search for information about an address or a set of coordinates.
#
def search(*args)
lookup.search(*args)
return [] if args[0].nil? || args[0] == ""
ip = (args.size == 1 and ip_address?(args.first))
lookup(ip).search(*args)
end
##
# Look up the coordinates of the given street address.
# Look up the coordinates of the given street or IP address.
#
def coordinates(address)
if (results = search(address)).size > 0
......@@ -41,23 +43,44 @@ module Geocoder
##
# Get the lookup object (which communicates with the remote geocoding API).
# Returns an IP address lookup if +ip+ parameter true.
#
def lookup
unless defined?(@lookup)
set_lookup Geocoder::Configuration.lookup
def lookup(ip = false)
if ip
get_lookup :freegeoip
else
get_lookup Geocoder::Configuration.lookup || :google
end
@lookup
end
def set_lookup(value)
if value == :yahoo
require "geocoder/lookups/yahoo"
@lookup = Geocoder::Lookup::Yahoo.new
else
require "geocoder/lookups/google"
@lookup = Geocoder::Lookup::Google.new
def get_lookup(name)
unless defined?(@lookups)
@lookups = {}
end
unless @lookups.include?(name)
@lookups[name] = spawn_lookup(name)
end
@lookups[name]
end
def spawn_lookup(name)
if valid_lookups.include?(name)
name = name.to_s
require "geocoder/lookups/#{name}"
eval("Geocoder::Lookup::#{name[0...1].upcase + name[1..-1]}.new")
end
end
def valid_lookups
[:google, :yahoo, :freegeoip]
end
##
# Does the given value look like an IP address?
#
def ip_address?(value)
value.match /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
end
end
Geocoder::Railtie.insert
require 'geocoder/lookups/base'
require 'geocoder/results/freegeoip'
module Geocoder::Lookup
class Freegeoip < Base
private # ---------------------------------------------------------------
def results(query, reverse = false)
begin
if doc = fetch_data(query, reverse)
[doc]
end
rescue StandardError # Freegeoip.net returns HTML on bad request
nil
end
end
def query_url(query, reverse = false)
"http://freegeoip.net/json/#{query}"
end
end
end
require 'geocoder/results/base'
module Geocoder::Result
class Freegeoip < Base
def coordinates
[latitude.to_f, longitude.to_f]
end
def address(format = :full)
"#{city}#{', ' + region_code unless region_code == ''} #{zipcode}, #{country_name}"
end
def self.response_attributes
%w[city region_code region_name metrocode zipcode
latitude longitude country_name country_code ip]
end
response_attributes.each do |a|
define_method a do
@data[a]
end
end
end
end
{
"city": "Plano",
"region_code": "TX",
"region_name": "Texas",
"metrocode": "623",
"zipcode": "75093",
"longitude": "-96.8134",
"country_name": "United States",
"country_code": "US",
"ip": "74.200.247.59",
"latitude": "33.0347"
}
......@@ -4,7 +4,6 @@ class GeocoderTest < Test::Unit::TestCase
def setup
Geocoder::Configuration.lookup = :google
Geocoder.send :set_lookup, :google
end
def test_fetch_coordinates
......@@ -49,16 +48,25 @@ class GeocoderTest < Test::Unit::TestCase
# --- Yahoo ---
def test_yahoo_result_components
Geocoder::Configuration.lookup = :yahoo
Geocoder.send :set_lookup, :yahoo
results = Geocoder.search("Madison Square Garden, New York, NY")
assert_equal "10001", results.first.postal
end
def test_yahoo_address_formatting
Geocoder::Configuration.lookup = :yahoo
Geocoder.send :set_lookup, :yahoo
results = Geocoder.search("Madison Square Garden, New York, NY")
assert_equal "Madison Square Garden, New York, NY 10001, United States",
results.first.address
end
# --- FreeGeoIp ---
def test_freegeoip_result_on_ip_address_search
results = Geocoder.search("74.200.247.59")
assert results.first.is_a?(Geocoder::Result::Freegeoip)
end
def test_freegeoip_result_components
results = Geocoder.search("74.200.247.59")
assert_equal "Plano, TX 75093, United States", results.first.address
end
end
......@@ -40,10 +40,24 @@ require "geocoder/lookups/base"
#
module Geocoder
module Lookup
class Base
class Google < Base
private #-----------------------------------------------------------------
def fetch_raw_data(query, reverse = false)
File.read(File.join("test", "fixtures", "#{Geocoder::Configuration.lookup}_madison_square_garden.json"))
File.read(File.join("test", "fixtures", "google_madison_square_garden.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"))
end
end
class Freegeoip < Base
private #-----------------------------------------------------------------
def fetch_raw_data(query, reverse = false)
File.read(File.join("test", "fixtures", "freegeoip_74_200_247_59.json"))
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