Permalink
Browse files

Released GeoLocation version 0.2.0: now with timezones, more tests, a…

…nd an updated README
  • Loading branch information...
1 parent 427292c commit 4731c794b735ebb0b8ed489047fba976b661002d @chrisyour chrisyour committed Aug 26, 2010
View
@@ -1,6 +1,6 @@
= Geo Location
-Geo Locate your users using their IP address via hostip.info or maxmind.com.
+Easily geo-locate your users using their IP address via hostip.info or maxmind.com. Super simple to setup, super simple to use. I've found that the data from HostIP and Max Mind differ slightly. Max Mind (paid) has a more complete and accurate database at the moment, but HostIP is growing. For more information about Max Mind visit http://www.maxmind.com/app/city and for more information about HostIP visit http://hostip.info
== Installation
@@ -20,13 +20,15 @@ config/initializers/geo_location_config.rb:
== HostIP Example
- ip = GeoLocation.find('24.24.24.24') # => {:city=>"Liverpool", :region=>"NY", :country=>"US", :latitude=>"43.1059", :longitude=>"-76.2099"}
+ location = GeoLocation.find('24.24.24.24') # => {:ip=>"24.24.24.24", :city=>"Liverpool", :region=>"NY", :country=>"US", :latitude=>"43.1059", :longitude=>"-76.2099", :timezone=>"America/New_York"}
- puts ip[:city] # => Liverpool
- puts ip[:region] # => NY
- puts ip[:country] # => US
- puts ip[:latitude] # => 43.1059
- puts ip[:longitude] # => -76.2099
+ puts location[:ip] # => 24.24.24.24
+ puts location[:city] # => Liverpool
+ puts location[:region] # => NY
+ puts location[:country] # => US
+ puts location[:latitude] # => 43.1059
+ puts location[:longitude] # => -76.2099
+ puts location[:timezone] # => America/New_York
== Max Mind Configuration
@@ -40,20 +42,24 @@ config/initializers/geo_location_config.rb:
GeoLocation::key = 'YOUR MaxMind.COM LICENSE KEY'
# This location will be used while you develop rather than hitting the maxmind.com api
# GeoLocation::dev = 'US,NY,Jamaica,40.676300,-73.775200' # IP: 24.24.24.24
+ # Use this IP in development mode (development and testing will give you 127.0.0.1)
+ # GeoLocation::dev_ip = '24.24.24.24'
end
== Max Mind Example
GeoLocation::use = :maxmind
GeoLocation::key = 'YOUR MaxMind.COM LICENSE KEY'
- ip = GeoLocation.find('24.24.24.24') # => {:city=>"Jamaica", :region=>"NY", :country=>"US", :latitude=>"40.676300", :longitude=>"-73.775200"}
-
- puts ip[:city] # => Jamaica
- puts ip[:region] # => NY
- puts ip[:country] # => US
- puts ip[:latitude] # => 40.676300
- puts ip[:longitude] # => -73.775200
+ location = GeoLocation.find('24.24.24.24') # => {:ip=>"24.24.24.24", :city=>"Jamaica", :region=>"NY", :country=>"US", :latitude=>"40.676300", :longitude=>"-73.775200", :timezone=>"America/New_York"}
+
+ puts location[:ip] # => 24.24.24.24
+ puts location[:city] # => Jamaica
+ puts location[:region] # => NY
+ puts location[:country] # => US
+ puts location[:latitude] # => 40.676300
+ puts location[:longitude] # => -73.775200
+ puts location[:timezone] # => America/New_York
== Copyright
View
@@ -1,5 +1,6 @@
require 'active_support/inflector'
-require 'geo_location/variables'
-require 'geo_location/geo_location'
require 'geo_location/version'
+require 'geo_location/timezones'
+require 'geo_location/geo_location'
+require 'geo_location/variables'
@@ -6,11 +6,14 @@ module GeoLocation
class << self
- def find(ip)
+ def find(ip=nil)
+ ip = GeoLocation::dev_ip unless GeoLocation::dev_ip.nil?
return nil unless valid_ip(ip)
return (GeoLocation::use == :maxmind) ? maxmind(ip) : hostip(ip)
end
+ private
+
def valid_ip(ip)
ip =~ /(([2]([0-4][0-9]|[5][0-5])|[0-1]?[0-9]?[0-9])[.]){3}(([2]([0-4][0-9]|[5][0-5])|[0-1]?[0-9]?[0-9]))/i
end
@@ -19,23 +22,13 @@ def valid_ip(ip)
# US,NY,Jamaica,40.676300,-73.775200
def maxmind(ip)
- unless GeoLocation::dev.nil? || GeoLocation::dev.empty?
- puts "WARNING: GeoLocation is using the dev location: #{GeoLocation::dev}"
- location = GeoLocation::dev.split(',')
- else
+ if GeoLocation::dev.nil? || GeoLocation::dev.empty?
url = "http://geoip3.maxmind.com/b?l=#{GeoLocation::key}&i=#{ip}"
uri = URI.parse(url)
- location = Net::HTTP.get_response(uri).body.split(',')
+ data_from_maxmind_http_response(ip, Net::HTTP.get_response(uri).body)
+ else
+ data_from_maxmind_http_response(ip, GeoLocation::dev)
end
-
- data = {}
- data[:country] = location[0]
- data[:region] = location[1]
- data[:city] = location[2]
- data[:latitude] = location[3]
- data[:longitude] = location[4]
-
- data
end
# == Sample XML output from hostip.info (http://api.hostip.info/?ip=12.215.42.19)
@@ -65,9 +58,34 @@ def maxmind(ip)
# </HostipLookupResultSet>
def hostip(ip)
- url = "http://api.hostip.info/?ip=#{ip}"
- uri = URI.parse(url)
- xml = Net::HTTP.get_response(uri).body
+ if GeoLocation::dev.nil? || GeoLocation::dev.empty?
+ url = "http://api.hostip.info/?ip=#{ip}"
+ uri = URI.parse(url)
+ data_from_hostip_http_response(ip, Net::HTTP.get_response(uri).body)
+ else
+ data_from_maxmind_http_response(ip, GeoLocation::dev)
+ end
+ end
+
+ # == Handle http response data from Max Mind
+ # string formatted body
+ def data_from_maxmind_http_response(ip, body)
+ location = body.split(',')
+ data = {}
+ data[:country] = location[0]
+ data[:region] = location[1]
+ data[:city] = location[2]
+ data[:latitude] = location[3]
+ data[:longitude] = location[4]
+ data[:ip] = ip
+ data[:timezone] = timezone(data[:country], data[:region])
+ data
+ end
+
+ # == Handle http response data from HostIP
+ # xml formatted body
+ def data_from_hostip_http_response(ip, body)
+ xml = body
location = REXML::Document.new(xml)
data = {}
@@ -95,6 +113,9 @@ def hostip(ip)
end
end
+ data[:ip] = ip
+ data[:timezone] = timezone(data[:country], data[:region])
+
data
end
@@ -0,0 +1,43 @@
+module GeoLocation
+
+ class << self
+
+ def timezone(country, region=nil)
+ build_timezones
+ return nil if GeoLocation::timezones.empty?
+ (region.nil? || region.empty?) ? GeoLocation::timezones[country.to_sym] : GeoLocation::timezones[country.to_sym][region.to_sym]
+ end
+
+ private
+
+ def build_timezones
+ if GeoLocation::timezones.empty?
+ data = {}
+
+ File.open("lib/geo_location/timezones.txt", "r") do |infile|
+ while (line = infile.gets)
+ zones = line.split("\n")
+ zones.each do |z|
+ zone = z.split(" ")
+ country = zone[0].to_sym
+ region = zone[1].to_sym
+ value = zone[2]
+
+ data[country] = {} if data[country].nil?
+ if region.to_s.empty?
+ data[country] = value
+ else
+ data[country][region] = value
+ end
+
+ end # end zones.each
+ end # end while
+ end # end file.open
+
+ GeoLocation::timezones = data
+ end # end unless
+ end
+
+ end
+
+end
Oops, something went wrong.

0 comments on commit 4731c79

Please sign in to comment.