Permalink
Browse files

Implemented initial state of geo_ip

  • Loading branch information...
1 parent 3b62b05 commit 53679cfdfa04867fedbb586833fc7c6038749c54 Jeroen Jacobs committed Jan 9, 2010
Showing with 120 additions and 38 deletions.
  1. +43 −3 README.rdoc
  2. +14 −22 Rakefile
  3. +1 −0 init.rb
  4. +37 −0 lib/geo_ip.rb
  5. +19 −0 spec/geo_ip_spec.rb
  6. +1 −0 spec/spec.opts
  7. +5 −6 test/helper.rb → spec/spec_helper.rb
  8. +0 −7 test/test_geo_ip.rb
View
@@ -1,6 +1,46 @@
-= geo_ip
+= GeoIp
-Description goes here.
+Retreive the geolocation of an IP address based on the {ipinfodb.com}[http://ipinfodb.com/] webservice.
+
+Consider making a donation to {ipinfodb.com}[http://ipinfodb.com/] at {http://ipinfodb.com/donate.php}[http://ipinfodb.com/donate.php]
+
+== Usage
+
+=== Retreive geolocation
+ GeoIp.remote_geolocation(ip_address)
+
+=== Example
+
+ # 209.85.227.104 = google.be (US)
+ GeoIp.remote_geolocation('209.85.227.104')
+
+returns:
+
+ {
+ :status=>"OK",
+ :ip=>"209.85.227.104"
+ :country_code=>"US",
+ :country_name=>"United States",
+ :region_code=>"06",
+ :region_name=>"California",
+ :city=>"Mountain View",
+ :zip_postal_code=>"94043",
+ :latitude=>"37.4192",
+ :longitude=>"-122.057",
+ :timezone=>"-8",
+ :gmt_offset=>"-8",
+ :dst_offset=>"-7",
+ }
+
+== Getting it
+
+GeoIp can be installed as a Ruby Gem:
+
+ gem install geo_ip
+
+Alternatively, you can also install it as a Rails plugin:
+
+ ./script/plugin install git://github.com/jeroenj/geo_ip.git
== Note on Patches/Pull Requests
@@ -14,4 +54,4 @@ Description goes here.
== Copyright
-Copyright (c) 2010 Jeroen Jacobs. See LICENSE for details.
+Copyright (c) 2010 Jeroen Jacobs, {redstorm sprl}[http://www.redstorm.be]. See LICENSE for details.
View
@@ -5,42 +5,34 @@ begin
require 'jeweler'
Jeweler::Tasks.new do |gem|
gem.name = "geo_ip"
- gem.summary = %Q{Retreive the geolocation of an IP address based on the ipinfodb.com webservice}
- gem.description = %Q{TODO: longer description of your gem}
- gem.email = "jacobsjeroen@gmail.com"
+ gem.summary = "Retreive the geolocation of an IP address based on the ipinfodb.com webservice"
+ gem.description = "A call to the ipinfodb.com will be done to retreive the geolocation based on the IP address. No need to include a database file in the application."
+ gem.email = "jj@redstorm.com"
gem.homepage = "http://github.com/jeroenj/geo_ip"
gem.authors = ["Jeroen Jacobs"]
- gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
+ gem.add_development_dependency "rspec", ">= 1.2.9"
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
end
Jeweler::GemcutterTasks.new
rescue LoadError
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
end
-require 'rake/testtask'
-Rake::TestTask.new(:test) do |test|
- test.libs << 'lib' << 'test'
- test.pattern = 'test/**/test_*.rb'
- test.verbose = true
+require 'spec/rake/spectask'
+Spec::Rake::SpecTask.new(:spec) do |spec|
+ spec.libs << 'lib' << 'spec'
+ spec.spec_files = FileList['spec/**/*_spec.rb']
end
-begin
- require 'rcov/rcovtask'
- Rcov::RcovTask.new do |test|
- test.libs << 'test'
- test.pattern = 'test/**/test_*.rb'
- test.verbose = true
- end
-rescue LoadError
- task :rcov do
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
- end
+Spec::Rake::SpecTask.new(:rcov) do |spec|
+ spec.libs << 'lib' << 'spec'
+ spec.pattern = 'spec/**/*_spec.rb'
+ spec.rcov = true
end
-task :test => :check_dependencies
+task :spec => :check_dependencies
-task :default => :test
+task :default => :spec
require 'rake/rdoctask'
Rake::RDocTask.new do |rdoc|
View
@@ -0,0 +1 @@
+require 'geo_ip'
View
@@ -0,0 +1,37 @@
+SERVICE_URL = "http://ipinfodb.com/ip_query.php"
+IPV4_REGEXP = /\A(?:25[0-5]|(?:2[0-4]|1\d|[1-9])?\d)(?:\.(?:25[0-5]|(?:2[0-4]|1\d|[1-9])?\d)){3}\z/
+
+require 'rubygems'
+require 'json'
+require 'uri'
+require 'net/http'
+
+class GeoIp
+ def self.remote_geolocation(ip)
+ raise "Invalid IP address" unless ip.to_s =~ IPV4_REGEXP
+
+ uri = SERVICE_URL + "?ip=#{ip}&output=json"
+ url = URI.parse(uri)
+ reply = JSON.parse(Net::HTTP.get(url))
+ location = convert_keys reply
+ end
+
+ private
+ def self.convert_keys(hash)
+ location = {}
+ location[:ip] = hash["Ip"]
+ location[:status] = hash["Status"]
+ location[:country_code] = hash["CountryCode"]
+ location[:country_name] = hash["CountryName"]
+ location[:region_code] = hash["RegionCode"]
+ location[:region_name] = hash["RegionName"]
+ location[:city] = hash["City"]
+ location[:zip_postal_code] = hash["ZipPostalCode"]
+ location[:latitude] = hash["Latitude"]
+ location[:longitude] = hash["Longitude"]
+ location[:timezone] = hash["Timezone"]
+ location[:gmt_offset] = hash["Gmtoffset"]
+ location[:dst_offset] = hash["Dstoffset"]
+ location
+ end
+end
View
@@ -0,0 +1,19 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+
+describe "GeoIp" do
+ it "should return the correct country for a public ip address" do
+ # 209.85.227.104 = google.be (US)
+ GeoIp.remote_geolocation('209.85.227.104')[:country_code].should == 'US'
+ GeoIp.remote_geolocation('209.85.227.104')[:country_name].should == 'United States'
+ end
+
+ it "should return the correct country for a private ip address" do
+ GeoIp.remote_geolocation('10.0.0.1')[:country_code].should == 'RD'
+ GeoIp.remote_geolocation('10.0.0.1')[:country_name].should == 'Reserved'
+ end
+
+ it "should return the correct country for localhost ip address" do
+ GeoIp.remote_geolocation('127.0.0.1')[:country_code].should == 'RD'
+ GeoIp.remote_geolocation('127.0.0.1')[:country_name].should == 'Reserved'
+ end
+end
View
@@ -0,0 +1 @@
+--color
@@ -1,10 +1,9 @@
-require 'rubygems'
-require 'test/unit'
-require 'shoulda'
-
-$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.dirname(__FILE__))
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
require 'geo_ip'
+require 'spec'
+require 'spec/autorun'
-class Test::Unit::TestCase
+Spec::Runner.configure do |config|
+
end
View
@@ -1,7 +0,0 @@
-require 'helper'
-
-class TestGeoIp < Test::Unit::TestCase
- should "probably rename this file and start testing for real" do
- flunk "hey buddy, you should probably rename this file and start testing for real"
- end
-end

0 comments on commit 53679cf

Please sign in to comment.