geo_loc 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +14 -0
- data/README.md +89 -0
- data/Rakefile +2 -0
- data/geo_loc.gemspec +27 -0
- data/lib/geo_loc.rb +68 -0
- data/lib/geo_loc/version.rb +3 -0
- data/spec/lib/geo_loc_spec.rb +100 -0
- data/spec/spec_helper.rb +84 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 85f8da0f505236bceaffc0b362d4343c3027795b
|
4
|
+
data.tar.gz: be4a7ab27768cc9889882a34953a10b5ef385576
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b247a7760ffc4f16c4160c29726f7a5578b685c2be34b48e94e536a0ffd6d36f904c657d6c58dab0b90b0406ee131f7b1695d263abefcd7db742ab287ae0cd4c
|
7
|
+
data.tar.gz: 7a6fc5fba322c615039c618bf91d35927f7cd7eea58bb9432a4e134587b67c85ce350716bf332177b57e56a8b1011195bb4314cf1b809eb2245061d5ff236387
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Copyright (c) 2014 Justin Wiley
|
2
|
+
|
3
|
+
This program is free software: you can redistribute it and/or modify
|
4
|
+
it under the terms of the GNU General Public License as published by
|
5
|
+
the Free Software Foundation, either version 3 of the License, or
|
6
|
+
(at your option) any later version.
|
7
|
+
|
8
|
+
This program is distributed in the hope that it will be useful,
|
9
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
GNU General Public License for more details.
|
12
|
+
|
13
|
+
You should have received a copy of the GNU General Public License
|
14
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# GeoLoc
|
2
|
+
|
3
|
+
A quick-and-dirty wrapper for the GeoIP gem that handles downloading and unzipping geodata.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'geo_loc'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install geo_loc
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Caveats:
|
24
|
+
|
25
|
+
- this gem is the minimum viable product for my purposes, your mileage may vary, feel free to fork and contribute if you run into issues
|
26
|
+
- it's designed for city level lookup resolution using Maxminds free city IP data, other lookup methods are not currently supported
|
27
|
+
- it assumes data files are .gzipped
|
28
|
+
|
29
|
+
The [GeoIP gem](https://github.com/cjheath/geoip) does a great job of accepting an IP address and digging through a MaxMind geolocation file to find a corresponding address.
|
30
|
+
|
31
|
+
One thing it doesn't do, however, is pull and unzip the data file for you. This gem attempts to add this functionality, by automatically downloading the file if necessary and storing it in a sensible directory (or directory of your choice).
|
32
|
+
|
33
|
+
### Typical usage
|
34
|
+
|
35
|
+
require 'geo_loc'
|
36
|
+
|
37
|
+
if gdata = GeoLoc.new.ip('10.0.0.1')
|
38
|
+
self.country = gdata[:country_code2]
|
39
|
+
self.state = gdata[:region_name]
|
40
|
+
self.city = gdata[:city_name]
|
41
|
+
self.zip = gdata[:postal_code]
|
42
|
+
self.lat = gdata[:latitude]
|
43
|
+
self.long = gdata[:longitude]
|
44
|
+
else
|
45
|
+
# ...sadness
|
46
|
+
end
|
47
|
+
|
48
|
+
This will download the latest release of Maxmind city data (see GeoIP gem for locations) if it doesn't already exist, and gzip it.
|
49
|
+
|
50
|
+
The #ip method rescues StandardError, so connectivity issues, file format issues will be logged and nil returned.
|
51
|
+
|
52
|
+
The hash returned by #ip comes directly from geoip, see geoip for details.
|
53
|
+
|
54
|
+
### Frequency of update
|
55
|
+
|
56
|
+
City data is **not** automatically refreshed. If you're deploying your application once a week or more frequently, and the data file is stored in a location that is overwritten after every deploy, this isn't an issue since the next time GeoLoc.new.ip executes it will pull the file. If it is an issue, you can manually force the sync data via:
|
57
|
+
|
58
|
+
GeoLoc.new.sync_data!
|
59
|
+
|
60
|
+
Since syncing will pull down and decompress an 11mb+ file, users may experience a delay the first time GeoLoc.new.ip executes. It's probably a good idea to do this as part of your deploy process.
|
61
|
+
|
62
|
+
Note that #sync_data! does not rescue exceptions.
|
63
|
+
|
64
|
+
### Overriding default locations
|
65
|
+
|
66
|
+
Without any initialization options, GeoLoc will try to pick default directory locations for you. If Rails is defined, it will use Rails.root + '/tmp'. If Rails isn't defined, it will use '/tmp'. An example of customized options:
|
67
|
+
|
68
|
+
GeoLoc.new(filename: 'my-file',
|
69
|
+
geodata_dir: 'my-dir',
|
70
|
+
geodata_file: 'geodata',
|
71
|
+
compressed_geodata_file: 'geodata.gz',
|
72
|
+
geodata_url: 'http://thedata.gz',
|
73
|
+
logger: MyLogger.new('/tmp/mylogger.log'))
|
74
|
+
|
75
|
+
In general, the options will work if only one is passed, for example if you want to customize the data where geodata is stored.
|
76
|
+
|
77
|
+
### Rspec warnings
|
78
|
+
|
79
|
+
warning: instance variable @data_exists not initialized
|
80
|
+
|
81
|
+
Is being triggered on running unit specs, if you know the cause and resolution to this issue, please let me know.
|
82
|
+
|
83
|
+
## Contributing
|
84
|
+
|
85
|
+
1. Fork it ( https://github.com/[my-github-username]/geo_loc/fork )
|
86
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
87
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
88
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
89
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/geo_loc.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'geo_loc/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "geo_loc"
|
8
|
+
spec.version = GeoLoc::VERSION
|
9
|
+
spec.authors = ["Justin Wiley"]
|
10
|
+
spec.email = ["justin.wiley@gmail.com"]
|
11
|
+
spec.summary = %q{A quick-and-dirty wrapper for the GeoIP gem that handles downloading and unzipping geodata}
|
12
|
+
spec.description = %q{A quick-and-dirty wrapper for the GeoIP gem that handles downloading and unzipping geodata}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "GPL V3"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "geoip", "~> 1.4.0"
|
22
|
+
|
23
|
+
spec.add_development_dependency "pry"
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
27
|
+
end
|
data/lib/geo_loc.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'geo_loc/version'
|
2
|
+
require 'geoip'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'zlib'
|
5
|
+
require 'logger'
|
6
|
+
|
7
|
+
# Geolocates given IP using maxminds geo ip database
|
8
|
+
# Pulls database down if it doesnt exists
|
9
|
+
# Note that in test environment (outside of mocked unit tests), will pull the ~11mb file, leading to lengthened initial test run
|
10
|
+
|
11
|
+
class GeoLoc
|
12
|
+
# FILENAME = 'GeoLiteCity.dat'
|
13
|
+
# GEODATA_FILE = File.join(Rails.root, '/tmp/', FILENAME)
|
14
|
+
# COMPRESSED_GEODATA_FILE = File.join(Rails.root, FILENAME + '.gz')
|
15
|
+
# GEODATA_URL = 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz'
|
16
|
+
|
17
|
+
attr_accessor :filename, :geodata_file, :geodata_dir, :compressed_geodata_file, :geodata_url, :logger
|
18
|
+
|
19
|
+
def initialize(filename: nil, geodata_dir: nil, geodata_file: nil, compressed_geodata_file: nil, geodata_url: nil, logger: nil)
|
20
|
+
self.filename = filename || 'GeoLiteCity.dat'
|
21
|
+
self.geodata_dir = geodata_dir || root_dir
|
22
|
+
self.geodata_file = geodata_file || File.join(self.geodata_dir, self.filename)
|
23
|
+
self.compressed_geodata_file = compressed_geodata_file || self.geodata_file + '.gz'
|
24
|
+
self.geodata_url = geodata_url || 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz'
|
25
|
+
self.logger = logger || logger_method
|
26
|
+
end
|
27
|
+
|
28
|
+
def logger_method; defined?(Rails) && Rails.respond_to?(:logger) ? Rails.logger : Logger.new('/tmp/geoloc.log'); end
|
29
|
+
def root_dir; defined?(Rails) && Rails.respond_to?(:root) ? File.join(Rails.root, '/tmp') : '/tmp'; end
|
30
|
+
|
31
|
+
def download_compressed_geodata
|
32
|
+
logger.info "Downloading geodata #{geodata_url}"
|
33
|
+
open(compressed_geodata_file, 'wb') {|f| f << open(geodata_url).read }
|
34
|
+
end
|
35
|
+
|
36
|
+
def decompress_geodata
|
37
|
+
logger.info "Decompressing #{compressed_geodata_file}"
|
38
|
+
File.open(compressed_geodata_file) do |cf|
|
39
|
+
begin
|
40
|
+
gz = Zlib::GzipReader.new(cf)
|
41
|
+
File.open(geodata_file, 'w'){|f| f << gz.read}
|
42
|
+
ensure
|
43
|
+
gz.close
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def sync_data!
|
49
|
+
download_compressed_geodata
|
50
|
+
decompress_geodata
|
51
|
+
end
|
52
|
+
|
53
|
+
def ip ip_address
|
54
|
+
begin
|
55
|
+
if @data_exists || File.exist?(geodata_file)
|
56
|
+
@data_exists = true
|
57
|
+
else
|
58
|
+
sync_data!
|
59
|
+
end
|
60
|
+
|
61
|
+
@geoip ||= GeoIP.new(geodata_file)
|
62
|
+
@geoip.city(ip_address).try(:to_hash)
|
63
|
+
rescue StandardError => e
|
64
|
+
logger.error "Failed to geo ip address #{ip_address}\n#{e}\n#{e.backtrace.join("\n")}"
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# require 'pry'
|
2
|
+
require_relative '../../lib/geo_loc.rb'
|
3
|
+
require_relative '../spec_helper'
|
4
|
+
|
5
|
+
describe GeoLoc do
|
6
|
+
let(:gl) { GeoLoc.new }
|
7
|
+
let(:gddir) { gl.geodata_dir }
|
8
|
+
let(:gdfile) { gl.geodata_file }
|
9
|
+
let(:gdzfile) { gl.compressed_geodata_file }
|
10
|
+
let(:gdurl) { gl.geodata_url }
|
11
|
+
let(:double_io) { double('IO', read: 'data')}
|
12
|
+
|
13
|
+
before do
|
14
|
+
GeoLoc.send(:remove_const, :Rails) if defined? GeoLoc::Rails
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'intialize' do
|
18
|
+
it 'provides default locations for storing geodata, url of where to download data from' do
|
19
|
+
gdfile.should be == "/tmp/GeoLiteCity.dat"
|
20
|
+
gddir.should be == '/tmp'
|
21
|
+
gdzfile.should be == "/tmp/GeoLiteCity.dat.gz"
|
22
|
+
gdurl.should be == "http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz"
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'allows these values to be overridden as options' do
|
26
|
+
gl = GeoLoc.new geodata_dir: '/mydir'
|
27
|
+
gl.geodata_dir.should be == '/mydir'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'uses Rails envrionment root dir if Rails is defined' do
|
31
|
+
class GeoLoc::Rails
|
32
|
+
def self.root; 'rails-root'; end
|
33
|
+
def self.logger; Logger.new('/dev/null'); end
|
34
|
+
end
|
35
|
+
gddir.should be == 'rails-root/tmp'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'refreshing geo ip data' do
|
40
|
+
before do
|
41
|
+
[gdzfile, gdfile].map{|f| FileUtils.rm(f) if File.exist?(f) }
|
42
|
+
end
|
43
|
+
|
44
|
+
it '#download_compressed_geodata pulls down compressed geoip data' do
|
45
|
+
gl.should_receive(:open).with(gdurl).and_return(double_io)
|
46
|
+
gl.should_receive(:open).with(gdzfile, 'wb').and_yield([])
|
47
|
+
|
48
|
+
gl.download_compressed_geodata
|
49
|
+
end
|
50
|
+
|
51
|
+
it '#decompress_geodata decompresses geodata using zlib' do
|
52
|
+
contents = 'test data'
|
53
|
+
Zlib::GzipWriter.open(gdzfile) do |gz|
|
54
|
+
gz.write contents
|
55
|
+
end
|
56
|
+
|
57
|
+
File.exist?(gdfile).should be_falsey
|
58
|
+
gl.decompress_geodata
|
59
|
+
res = File.read(gdfile)
|
60
|
+
res.should be == contents
|
61
|
+
end
|
62
|
+
|
63
|
+
it '#sync_data! does both, downloads and decompresses' do
|
64
|
+
gl.should_receive(:download_compressed_geodata)
|
65
|
+
gl.should_receive(:decompress_geodata)
|
66
|
+
gl.sync_data!
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#ip' do
|
71
|
+
let(:double_geoip) { double(GeoIP, city: 'city data') }
|
72
|
+
let(:ip) { '127.0.0.1' }
|
73
|
+
|
74
|
+
it 'returns the geo data for a given ip address' do
|
75
|
+
gl.stub(:sync_data!)
|
76
|
+
double_geoip.should_receive(:city).with(ip)
|
77
|
+
GeoIP.should_receive(:new).with(gdfile).and_return(double_geoip)
|
78
|
+
gl.ip(ip)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'should sync the data file if it doesnt exist' do
|
82
|
+
File.should_receive(:exist?).and_return(false)
|
83
|
+
gl.should_receive(:sync_data!)
|
84
|
+
GeoIP.should_receive(:new).with(gdfile).and_return(double_geoip)
|
85
|
+
gl.ip(ip)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should not sync if it does' do
|
89
|
+
File.should_receive(:exist?).and_return(true)
|
90
|
+
gl.should_not_receive(:sync_data!)
|
91
|
+
GeoIP.should_receive(:new).with(gdfile).and_return(double_geoip)
|
92
|
+
gl.ip(ip)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'rescues exceptions, returning nil' do
|
96
|
+
File.should_receive(:exist?).and_raise(StandardError)
|
97
|
+
gl.ip(ip).should be_nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause this
|
4
|
+
# file to always be loaded, without a need to explicitly require it in any files.
|
5
|
+
#
|
6
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
7
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
8
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
9
|
+
# individual file that may not need all of that loaded. Instead, make a
|
10
|
+
# separate helper file that requires this one and then use it only in the specs
|
11
|
+
# that actually need it.
|
12
|
+
#
|
13
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
14
|
+
# users commonly want.
|
15
|
+
#
|
16
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
17
|
+
RSpec.configure do |config|
|
18
|
+
# The settings below are suggested to provide a good initial experience
|
19
|
+
# with RSpec, but feel free to customize to your heart's content.
|
20
|
+
config.expect_with :rspec do |c|
|
21
|
+
c.syntax = :should
|
22
|
+
end
|
23
|
+
config.mock_with :rspec do |c|
|
24
|
+
c.syntax = :should
|
25
|
+
end
|
26
|
+
=begin
|
27
|
+
# These two settings work together to allow you to limit a spec run
|
28
|
+
# to individual examples or groups you care about by tagging them with
|
29
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
30
|
+
# get run.
|
31
|
+
config.filter_run :focus
|
32
|
+
config.run_all_when_everything_filtered = true
|
33
|
+
|
34
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
35
|
+
# file, and it's useful to allow more verbose output when running an
|
36
|
+
# individual spec file.
|
37
|
+
if config.files_to_run.one?
|
38
|
+
# Use the documentation formatter for detailed output,
|
39
|
+
# unless a formatter has already been configured
|
40
|
+
# (e.g. via a command-line flag).
|
41
|
+
config.default_formatter = 'doc'
|
42
|
+
end
|
43
|
+
|
44
|
+
# Print the 10 slowest examples and example groups at the
|
45
|
+
# end of the spec run, to help surface which specs are running
|
46
|
+
# particularly slow.
|
47
|
+
config.profile_examples = 10
|
48
|
+
|
49
|
+
# Run specs in random order to surface order dependencies. If you find an
|
50
|
+
# order dependency and want to debug it, you can fix the order by providing
|
51
|
+
# the seed, which is printed after each run.
|
52
|
+
# --seed 1234
|
53
|
+
config.order = :random
|
54
|
+
|
55
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
56
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
57
|
+
# test failures related to randomization by passing the same `--seed` value
|
58
|
+
# as the one that triggered the failure.
|
59
|
+
Kernel.srand config.seed
|
60
|
+
|
61
|
+
# rspec-expectations config goes here. You can use an alternate
|
62
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
63
|
+
# assertions if you prefer.
|
64
|
+
config.expect_with :rspec do |expectations|
|
65
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
66
|
+
# For more details, see:
|
67
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
68
|
+
expectations.syntax = :expect
|
69
|
+
end
|
70
|
+
|
71
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
72
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
73
|
+
config.mock_with :rspec do |mocks|
|
74
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
75
|
+
# For more details, see:
|
76
|
+
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
77
|
+
mocks.syntax = :expect
|
78
|
+
|
79
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
80
|
+
# a real object. This is generally recommended.
|
81
|
+
mocks.verify_partial_doubles = true
|
82
|
+
end
|
83
|
+
=end
|
84
|
+
end
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: geo_loc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Justin Wiley
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-08-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: geoip
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.4.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.4.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
description: A quick-and-dirty wrapper for the GeoIP gem that handles downloading
|
84
|
+
and unzipping geodata
|
85
|
+
email:
|
86
|
+
- justin.wiley@gmail.com
|
87
|
+
executables: []
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- ".rspec"
|
93
|
+
- Gemfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- geo_loc.gemspec
|
98
|
+
- lib/geo_loc.rb
|
99
|
+
- lib/geo_loc/version.rb
|
100
|
+
- spec/lib/geo_loc_spec.rb
|
101
|
+
- spec/spec_helper.rb
|
102
|
+
homepage: ''
|
103
|
+
licenses:
|
104
|
+
- GPL V3
|
105
|
+
metadata: {}
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubyforge_project:
|
122
|
+
rubygems_version: 2.2.2
|
123
|
+
signing_key:
|
124
|
+
specification_version: 4
|
125
|
+
summary: A quick-and-dirty wrapper for the GeoIP gem that handles downloading and
|
126
|
+
unzipping geodata
|
127
|
+
test_files:
|
128
|
+
- spec/lib/geo_loc_spec.rb
|
129
|
+
- spec/spec_helper.rb
|