geo_ip 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/geo_ip.rb +23 -25
- data/spec/geo_ip_spec.rb +49 -58
- metadata +5 -5
data/lib/geo_ip.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
SERVICE_URL = "http://api.ipinfodb.com/v2/"
|
2
|
-
CITY_API = "ip_query.php"
|
3
|
-
COUNTRY_API = "ip_query_country.php"
|
4
|
-
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/
|
5
|
-
|
6
1
|
require 'json'
|
7
2
|
require 'rest-client'
|
8
3
|
|
9
4
|
class GeoIp
|
5
|
+
SERVICE_URL = 'http://api.ipinfodb.com/v3/ip-'
|
6
|
+
CITY_API = 'city'
|
7
|
+
COUNTRY_API = 'country'
|
8
|
+
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/
|
9
|
+
|
10
10
|
@@api_key = nil
|
11
11
|
@@timeout = 1
|
12
12
|
|
@@ -38,33 +38,31 @@ class GeoIp
|
|
38
38
|
def geolocation ip, options={}
|
39
39
|
@precision = options[:precision] || :city
|
40
40
|
@timezone = options[:timezone] || false
|
41
|
-
raise
|
42
|
-
raise
|
43
|
-
raise
|
44
|
-
raise
|
45
|
-
url = "#{SERVICE_URL}#{@
|
46
|
-
|
47
|
-
|
41
|
+
raise 'API key must be set first: GeoIp.api_key = \'YOURKEY\'' if self.api_key.nil?
|
42
|
+
raise 'Invalid IP address' unless ip.to_s =~ IPV4_REGEXP
|
43
|
+
raise 'Invalid precision' unless [:country, :city].include?(@precision)
|
44
|
+
raise 'Invalid timezone' unless [true, false].include?(@timezone)
|
45
|
+
url = "#{SERVICE_URL}#{@precision == :city || @timezone ? CITY_API : COUNTRY_API}?key=#{api_key}&ip=#{ip}&format=json&timezone=#{@timezone}"
|
46
|
+
parsed_response = JSON.parse RestClient::Request.execute(:method => :get, :url => url, :timeout => self.timeout)
|
47
|
+
convert_keys parsed_response
|
48
48
|
end
|
49
49
|
|
50
50
|
private
|
51
51
|
def convert_keys hash
|
52
52
|
location = {}
|
53
|
-
location[:ip]
|
54
|
-
location[:
|
55
|
-
location[:
|
56
|
-
location[:
|
53
|
+
location[:ip] = hash['ipAddress']
|
54
|
+
location[:status_code] = hash['statusCode']
|
55
|
+
location[:status_message] = hash['statusMessage']
|
56
|
+
location[:country_code] = hash['countryCode']
|
57
|
+
location[:country_name] = hash['countryName']
|
57
58
|
if @precision == :city
|
58
|
-
location[:
|
59
|
-
location[:
|
60
|
-
location[:
|
61
|
-
location[:
|
62
|
-
location[:
|
63
|
-
location[:longitude] = hash["Longitude"]
|
59
|
+
location[:region_name] = hash['regionName']
|
60
|
+
location[:city] = hash['cityName']
|
61
|
+
location[:zip_code] = hash['zipCode']
|
62
|
+
location[:latitude] = hash['latitude']
|
63
|
+
location[:longitude] = hash['longitude']
|
64
64
|
if @timezone
|
65
|
-
location[:
|
66
|
-
location[:utc_offset] = hash["Gmtoffset"].to_i
|
67
|
-
location[:dst?] = hash["Isdst"] ? true : false
|
65
|
+
location[:timezone] = hash['timeZone']
|
68
66
|
end
|
69
67
|
end
|
70
68
|
location
|
data/spec/geo_ip_spec.rb
CHANGED
@@ -3,109 +3,100 @@ IP_GOOGLE_US = '209.85.227.104'
|
|
3
3
|
IP_PRIVATE = '10.0.0.1'
|
4
4
|
IP_LOCAL = '127.0.0.1'
|
5
5
|
|
6
|
-
describe
|
7
|
-
|
6
|
+
describe 'GeoIp' do
|
8
7
|
before :each do
|
9
8
|
api_config = YAML.load_file(File.dirname(__FILE__) + '/api.yml')
|
10
9
|
GeoIp.api_key = api_config['key']
|
11
10
|
end
|
12
11
|
|
13
|
-
context
|
14
|
-
it
|
15
|
-
GeoIp.api_key =
|
16
|
-
GeoIp.api_key.should ==
|
12
|
+
context 'api_key' do
|
13
|
+
it 'should return the API key when set' do
|
14
|
+
GeoIp.api_key = 'my_api_key'
|
15
|
+
GeoIp.api_key.should == 'my_api_key'
|
17
16
|
end
|
18
17
|
|
19
|
-
it
|
18
|
+
it 'should throw an error when API key is not set' do
|
20
19
|
GeoIp.api_key = nil
|
21
20
|
lambda {GeoIp.geolocation(IP_GOOGLE_US)}.should raise_error
|
22
21
|
end
|
23
22
|
end
|
24
23
|
|
25
|
-
context
|
26
|
-
it
|
24
|
+
context 'city' do
|
25
|
+
it 'should return the correct city for a public ip address' do
|
27
26
|
geolocation = GeoIp.geolocation(IP_GOOGLE_US)
|
28
27
|
geolocation[:country_code].should == 'US'
|
29
|
-
geolocation[:country_name].should == '
|
30
|
-
geolocation[:city].should == '
|
28
|
+
geolocation[:country_name].should == 'UNITED STATES'
|
29
|
+
geolocation[:city].should == 'MONTEREY PARK'
|
31
30
|
end
|
32
31
|
|
33
|
-
it
|
32
|
+
it 'should return nothing city for a private ip address' do
|
34
33
|
geolocation = GeoIp.geolocation(IP_PRIVATE)
|
35
|
-
geolocation[:country_code].should == '
|
36
|
-
geolocation[:country_name].should == '
|
37
|
-
geolocation[:city].should
|
34
|
+
geolocation[:country_code].should == '-'
|
35
|
+
geolocation[:country_name].should == '-'
|
36
|
+
geolocation[:city].should == '-'
|
38
37
|
end
|
39
38
|
|
40
|
-
it
|
39
|
+
it 'should return nothing for localhost ip address' do
|
41
40
|
geolocation = GeoIp.geolocation(IP_LOCAL)
|
42
|
-
geolocation[:country_code].should == '
|
43
|
-
geolocation[:country_name].should == '
|
44
|
-
geolocation[:city].should
|
41
|
+
geolocation[:country_code].should == '-'
|
42
|
+
geolocation[:country_name].should == '-'
|
43
|
+
geolocation[:city].should == '-'
|
45
44
|
end
|
46
45
|
|
47
|
-
it
|
48
|
-
geolocation = GeoIp.geolocation(IP_GOOGLE_US,
|
46
|
+
it 'should return the correct city for a public ip address when explicitly requiring it' do
|
47
|
+
geolocation = GeoIp.geolocation(IP_GOOGLE_US, :precision => :city)
|
49
48
|
geolocation[:country_code].should == 'US'
|
50
|
-
geolocation[:country_name].should == '
|
51
|
-
geolocation[:city].should == '
|
49
|
+
geolocation[:country_name].should == 'UNITED STATES'
|
50
|
+
geolocation[:city].should == 'MONTEREY PARK'
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
55
|
-
context
|
56
|
-
it
|
57
|
-
geolocation = GeoIp.geolocation(IP_GOOGLE_US,
|
54
|
+
context 'country' do
|
55
|
+
it 'should return the correct country for a public ip address' do
|
56
|
+
geolocation = GeoIp.geolocation(IP_GOOGLE_US, :precision => :country)
|
58
57
|
geolocation[:country_code].should == 'US'
|
59
|
-
geolocation[:country_name].should == '
|
58
|
+
geolocation[:country_name].should == 'UNITED STATES'
|
60
59
|
end
|
61
60
|
|
62
|
-
it
|
63
|
-
geolocation = GeoIp.geolocation(IP_PRIVATE,
|
64
|
-
geolocation[:country_code].should == '
|
65
|
-
geolocation[:country_name].should == '
|
61
|
+
it 'should return nothing country for a private ip address' do
|
62
|
+
geolocation = GeoIp.geolocation(IP_PRIVATE, :precision => :country)
|
63
|
+
geolocation[:country_code].should == '-'
|
64
|
+
geolocation[:country_name].should == '-'
|
66
65
|
end
|
67
66
|
|
68
|
-
it
|
69
|
-
geolocation = GeoIp.geolocation(IP_LOCAL,
|
70
|
-
geolocation[:country_code].should == '
|
71
|
-
geolocation[:country_name].should == '
|
67
|
+
it 'should return nothing country for localhost ip address' do
|
68
|
+
geolocation = GeoIp.geolocation(IP_LOCAL, :precision => :country)
|
69
|
+
geolocation[:country_code].should == '-'
|
70
|
+
geolocation[:country_name].should == '-'
|
72
71
|
end
|
73
72
|
|
74
|
-
it
|
75
|
-
geolocation = GeoIp.geolocation(IP_GOOGLE_US,
|
73
|
+
it 'should not return the city for a public ip address' do
|
74
|
+
geolocation = GeoIp.geolocation(IP_GOOGLE_US, :precision => :country)
|
76
75
|
geolocation[:country_code].should == 'US'
|
77
|
-
geolocation[:country_name].should == '
|
76
|
+
geolocation[:country_name].should == 'UNITED STATES'
|
78
77
|
geolocation[:city].should be_nil
|
79
78
|
end
|
80
79
|
end
|
81
80
|
|
82
|
-
context
|
83
|
-
it
|
84
|
-
geolocation = GeoIp.geolocation(IP_GOOGLE_US,
|
85
|
-
geolocation[:
|
86
|
-
geolocation[:dst?].should_not be_nil # true if dst?, false if not dst?
|
87
|
-
geolocation[:utc_offset].should == (geolocation[:dst?] ? -25200 : -28800)
|
81
|
+
context 'timezone' do
|
82
|
+
it 'should return the correct timezone information for a public ip address' do
|
83
|
+
geolocation = GeoIp.geolocation(IP_GOOGLE_US, :timezone => true)
|
84
|
+
geolocation[:timezone].should == '-08:00' # This one is likely to break when dst changes.
|
88
85
|
end
|
89
86
|
|
90
|
-
it
|
91
|
-
geolocation = GeoIp.geolocation(IP_GOOGLE_US,
|
92
|
-
geolocation[:
|
93
|
-
geolocation[:utc_offset].should be_nil
|
94
|
-
geolocation[:dst?].should be_nil
|
87
|
+
it 'should not return the timezone information when explicitly not requesting it' do
|
88
|
+
geolocation = GeoIp.geolocation(IP_GOOGLE_US, :timezone => false)
|
89
|
+
geolocation[:timezone].should be_nil
|
95
90
|
end
|
96
91
|
|
97
|
-
it
|
92
|
+
it 'should not return the timezone information when not requesting it' do
|
98
93
|
geolocation = GeoIp.geolocation(IP_GOOGLE_US)
|
99
|
-
geolocation[:
|
100
|
-
geolocation[:utc_offset].should be_nil
|
101
|
-
geolocation[:dst?].should be_nil
|
94
|
+
geolocation[:timezone].should be_nil
|
102
95
|
end
|
103
96
|
|
104
|
-
it
|
105
|
-
geolocation = GeoIp.geolocation(IP_GOOGLE_US,
|
106
|
-
geolocation[:
|
107
|
-
geolocation[:utc_offset].should be_nil
|
108
|
-
geolocation[:dst?].should be_nil
|
97
|
+
it 'should not return the timezone information when country precision is selected' do
|
98
|
+
geolocation = GeoIp.geolocation(IP_GOOGLE_US, :precision => :country, :timezone => true)
|
99
|
+
geolocation[:timezone].should be_nil
|
109
100
|
end
|
110
101
|
end
|
111
102
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geo_ip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jeroen Jacobs
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-05-
|
18
|
+
date: 2011-05-29 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|