Skip to content

Commit

Permalink
Released GeoLocation version 0.2.0: now with timezones, more tests, a…
Browse files Browse the repository at this point in the history
…nd an updated README
  • Loading branch information
chrisyour committed Aug 26, 2010
1 parent 427292c commit 4731c79
Show file tree
Hide file tree
Showing 8 changed files with 904 additions and 50 deletions.
34 changes: 20 additions & 14 deletions README.rdoc
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
5 changes: 3 additions & 2 deletions lib/geo_location.rb
Original file line number Diff line number Diff line change
@@ -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'
57 changes: 39 additions & 18 deletions lib/geo_location/geo_location.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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 = {}
Expand Down Expand Up @@ -95,6 +113,9 @@ def hostip(ip)
end
end

data[:ip] = ip
data[:timezone] = timezone(data[:country], data[:region])

data
end

Expand Down
43 changes: 43 additions & 0 deletions lib/geo_location/timezones.rb
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 4731c79

Please sign in to comment.