geolocal 0.6.2 → 0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a576db50e71f6e445ffd7159ca299f6301bcbd71
4
- data.tar.gz: 548b0a82bc3e3459e7b2eb7e09ff40b898a654c1
3
+ metadata.gz: 9967a2d045173bb94fd0a2099f9751d6c485d5e2
4
+ data.tar.gz: 68ccf53dc8987083ea502b65d27742c6f23e29c2
5
5
  SHA512:
6
- metadata.gz: e6d417f096f6cb0bf601c4d74bd698a951766cd37bca686af96fcd66c8c43a92d8f48c8b773d436496a24897f73e7de8f7d6a9c2c82aca91ddd4b78306cf9757
7
- data.tar.gz: eb79ad467e23ecf5e5d47e262e6ae7a0577b96e261971175bf9a1714f155ad9b53f61d46224546ba73b418ccabfd8a1ad97dd56a90fb606f2ec3444bb1ee23d8
6
+ metadata.gz: 95eb28b17e6676f41ea1684eb156ae562bd56a8d91dca3368c9a43f21f5c039e4969722a5f5830439406436de5ba32ada049f91b79f284645f1810c82a013dad
7
+ data.tar.gz: 218051f783714e1cdfdf988f3e6e76da636fcc3d4c0b71f4016ed5932e409ea1b246698e0baf13bab07ba5b7235c0333540bece81d149aa4515b3fdf20780626
data/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # Geolocal
2
2
 
3
3
  Allows IP addresses to geocoded with a single Ruby if statement.
4
- No network access, no context switches, no delay. Just one low-calorie local lookup.
5
-
4
+ No network access, no context switches, no delay. Just one low-calorie lookup:
5
+ `Geolocal.in_spain?(request.remote_ip)`
6
6
 
7
7
  ## Installation
8
8
 
9
- The usual method, add this line to your Gemfile:
9
+ Add this line to your Gemfile:
10
10
 
11
11
  ```ruby
12
12
  gem 'geolocal'
@@ -15,38 +15,47 @@ gem 'geolocal'
15
15
 
16
16
  ## Usage
17
17
 
18
- First create a config file that describes the ranges you're interested in.
18
+ If you're using Rails, run `rails generate geolocal` to create the configuration file.
19
+ Otherwise, crib from [config/geolocal.rb](https://github.com/bronson/geolocal/tree/master/config/geolocal.rb).
20
+
21
+ The config file describes the ranges you're interested in.
19
22
  Here's an example:
20
23
 
21
24
  ```ruby
22
25
  Geolocal.configure do
23
26
  config.countries = {
24
27
  us: 'US',
28
+ spain: 'ES',
25
29
  central_america: %w[ BZ CR SV GT HN NI PA ]
26
30
  }
27
31
  end
28
32
  ```
29
33
 
30
- Now run `rake geolocal:update`. It will download the geocoding data
34
+ Now run `rake geolocal:update`. Geolocal downloads the geocoding data
31
35
  from the default provider (see the [providers](#providers) section) and
32
- create `lib/geolocal.rb`.
36
+ creates the desired methods:
33
37
 
34
38
  ```ruby
35
39
  Geolocal.in_us?(request.remote_ip)
36
- Geolocal.in_central_america?(IPAddr.new('200.16.66.0'))
40
+ Geolocal.in_spain?('2a05:af06::') # optional IPv6 support
41
+ Geolocal.in_central_america?('200.16.66.0')
37
42
  ```
38
43
 
39
- You can pass:
44
+ #### The in\_*area*? method
45
+
46
+ The `rake geolocal:update` task generates the Ruby file defining these methods. You can pass:
40
47
  * a string: `Geolocal.in_us?("10.1.2.3")`
41
48
  * an [IPAddr](http://www.ruby-doc.org/stdlib-2.2.0/libdoc/ipaddr/rdoc/IPAddr.html) object:
42
49
  `Geolocal.in_eu?(IPAddr.new('2.16.54.0'))`
43
- * an integer/family combo: `Geolocal.in_us?(167838211, Socket::AF_INET)`
50
+ * an integer/family combo: `Geolocal.in_asia?(167838211, Socket::AF_INET)`
51
+
52
+ It returns true if the IP address is in the area, false if not.
44
53
 
45
54
  ## Config
46
55
 
47
56
  Here are the supported configuration options:
48
57
 
49
- * **provider**: Where to download the geocoding data. Default: DB_IP.
58
+ * **provider**: Where to download the geocoding data. See [Providers](#providers) below. Default: DB_IP.
50
59
  * **module**: The name of the module to receive the `in_*` methods. Default: 'Geolocal'.
51
60
  * **file**: Path to the file to contain the generated code. Default: `lib/#{module}.rb`.
52
61
  * **tmpdir**: the directory to contain intermediate files. They will require tens of megabytes
@@ -57,8 +66,20 @@ Here are the supported configuration options:
57
66
 
58
67
  ## Examples
59
68
 
60
- This uses the [Countries](https://github.com/hexorx/countries) gem
61
- to discover if an address is in the European Union:
69
+ There are some examples in the [contrib](https://github.com/bronson/geolocal/tree/master/contrib) directory.
70
+ Run them like this:
71
+
72
+ ```sh
73
+ git clone https://github.com/bronson/geolocal
74
+ cd geolocal
75
+ rake geolocal config=contrib/continents.rb
76
+ ```
77
+
78
+
79
+ #### in_eu?
80
+
81
+ It's easy to use the [Countries](https://github.com/hexorx/countries) gem
82
+ to create a `Geolocal.in_eu?(ip_addr)` method:
62
83
 
63
84
  ```ruby
64
85
  require 'countries'
@@ -70,13 +91,15 @@ Geolocal.configure do |config|
70
91
  end
71
92
  ```
72
93
 
73
- Now you can call `Geolocal.in_eu?(ip)`. If the European Union membership ever changes,
74
- run `bundle update countries` and then `rake geolocal` to bring your app up to date.
94
+ If European Union membership ever changes, just run `bundle update countries`
95
+ and `rake geolocal` to bring your app back up to date.
96
+
97
+
75
98
 
76
99
  ## Providers
77
100
 
78
- This gem currently only supoports the [DB-IP](https://db-ip.com/about/) database.
79
- There are lots of other databases available and this gem is organized to support them.
101
+ This gem currently only supoports the [DB-IP](https://db-ip.com/about/) Countries database.
102
+ There are lots of other databases available and this gem is organized to support them one day.
80
103
  Patches welcome.
81
104
 
82
105
 
@@ -91,8 +114,7 @@ environments like Heroku.
91
114
 
92
115
  ## TODO
93
116
 
94
- - [ ] include a Rails generator for the config file?
95
- - [ ] performance information? benchmarks. space saving by going ipv4-only?
117
+ - [ ] performance information / benchmarks?
96
118
  - [ ] Add support for cities
97
119
  - [ ] other sources for this data? [MainFacts](http://mainfacts.com/ip-address-space-addresses), [NirSoft](http://www.nirsoft.net/countryip/)
98
120
  Also maybe allow providers to accept their own options?
data/config/geolocal.rb CHANGED
@@ -1,5 +1,17 @@
1
1
  require 'geolocal'
2
2
 
3
3
  Geolocal.configure do |config|
4
+ # This example creates a Geolocal.in_us?(addr) command:
4
5
  config.countries = { us: 'US' }
6
+
7
+ # This is where the output goes. You should commit it to your project.
8
+ # config.module = 'Geolocal'
9
+ # config.file = 'lib/geolocal.rb'
10
+
11
+ # If your host is IPv4 only, you can save space by omitting IPv6 data and vice versa.
12
+ # config.ipv6 = true
13
+ # config.ipv4 = true
14
+
15
+ # Download and process the geocoding data in this directory. Don't commit it.
16
+ # config.tmpdir = './tmp/geolocal'
5
17
  end
@@ -0,0 +1,23 @@
1
+ require 'benchmark'
2
+
3
+ # This shows that Ranges are about twice as fast as 2-element Arrays
4
+ # Unless the range is (1.to_i..2.to_i), which is identical to Arrays
5
+
6
+ N = 10_000_000
7
+
8
+ $a = []
9
+ $r = []
10
+
11
+ def array
12
+ $a << [1,2]
13
+ end
14
+
15
+ def range
16
+ $r << (1..2)
17
+ end
18
+
19
+ Benchmark.bm(15, 'array/range') do |x|
20
+ array_report = x.report('array:') { N.times { array } }
21
+ range_report = x.report('range:') { N.times { range } }
22
+ [array_report / range_report]
23
+ end
@@ -0,0 +1,20 @@
1
+ require 'geolocal'
2
+ require 'countries'
3
+
4
+
5
+ # creates in_x? methods for each continent: in_north_america?, in_europe?, etc.
6
+
7
+ Geolocal.configure do |config|
8
+ all_countries = Country.all.map { |c| Country[c[1]] }
9
+
10
+ # { 'antarctica' => ['AQ', 'BV', ...], 'australia' => ['AS', 'AU', ...], ... }
11
+ by_continent = all_countries.reduce({}) { |hash,country|
12
+ continent = country.continent.downcase;
13
+ hash[continent] ||= [];
14
+ hash[continent] << country.alpha2;
15
+ hash
16
+ }
17
+
18
+ config.countries = by_continent
19
+ config.ipv6 = false
20
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Creates a US-centric config file for Geolocal
3
+
4
+ Example:
5
+ rails generate geolocal
6
+
7
+ This will create:
8
+ config/geolocal.rb
@@ -0,0 +1,7 @@
1
+ class GeolocalGenerator < Rails::Generators::Base
2
+ source_root File.expand_path('../templates', __FILE__)
3
+
4
+ def copy_config_file
5
+ copy_file 'geolocal.rb', 'config/geolocal.rb'
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ require 'geolocal'
2
+
3
+ Geolocal.configure do |config|
4
+ # This example creates a Geolocal.in_us?(addr) command:
5
+ config.countries = { us: 'US' }
6
+
7
+ # This is where the output goes. You should commit it to your project.
8
+ # config.module = 'Geolocal'
9
+ # config.file = 'lib/geolocal.rb'
10
+
11
+ # If your host is IPv4 only, you can save space by omitting IPv6 data and vice versa.
12
+ # config.ipv6 = true
13
+ # config.ipv4 = true
14
+
15
+ # Download and process the geocoding data in this directory. Don't commit it.
16
+ # config.tmpdir = './tmp/geolocal'
17
+ end
@@ -21,29 +21,42 @@ module Geolocal
21
21
  hiaddr = IPAddr.new(histr)
22
22
  lofam = loaddr.family
23
23
  hifam = hiaddr.family
24
- raise "#{lostr} is family #{lofam} but #{histr} is #{hifam}" if lofam != hifam
24
+ if lofam != hifam
25
+ raise "#{lostr} and #{histr} must be in the same address family"
26
+ end
27
+
28
+ loval = loaddr.to_i
29
+ hival = hiaddr.to_i
30
+ if loval > hival
31
+ raise "range supplied in the wrong order: #{lostr}..#{histr}"
32
+ end
25
33
 
26
34
  if lofam == Socket::AF_INET
27
- namefam = name + 'v4' if config[:ipv4]
35
+ namefam = name.upcase + 'v4' if config[:ipv4]
28
36
  elsif lofam == Socket::AF_INET6
29
- namefam = name + 'v6' if config[:ipv6]
37
+ namefam = name.upcase + 'v6' if config[:ipv6]
30
38
  else
31
- raise "unknown family #{lofam} for #{lostr}"
39
+ raise "unknown address family #{lofam} for #{lostr}"
32
40
  end
33
41
 
34
42
  if namefam
35
- results[namefam] << "#{loaddr.to_i}..#{hiaddr.to_i},\n"
43
+ results[namefam] << (loaddr.to_i..hiaddr.to_i)
36
44
  end
45
+ namefam
37
46
  end
38
47
 
39
- def update
40
- countries = config[:countries].reduce({}) { |a, (k, v)|
41
- a.merge! k.to_s.upcase => Array(v).map(&:upcase).to_set
48
+ def countries
49
+ @countries ||= config[:countries].sort_by { |k, v| k }.reduce({}) { |a, (k, v)|
50
+ k = k.to_s.gsub(/[ -]/, '_')
51
+ raise "invalid identifier: '#{k}'" if k =~ /^[^A-Za-z_]|[^A-Za-z0-9_]|^\s*$/
52
+ a.merge! k.to_s.downcase => Array(v).map { |c| c.to_s.upcase }.sort.to_set
42
53
  }
54
+ end
43
55
 
56
+ def update
44
57
  results = countries.keys.reduce({}) { |a, k|
45
- a.merge! k.upcase+'v4' => '' if config[:ipv4]
46
- a.merge! k.upcase+'v6' => '' if config[:ipv6]
58
+ a.merge! k.upcase+'v4' => [] if config[:ipv4]
59
+ a.merge! k.upcase+'v6' => [] if config[:ipv6]
47
60
  a
48
61
  }
49
62
 
@@ -70,7 +83,7 @@ module Geolocal
70
83
 
71
84
  write_header file, modname
72
85
 
73
- config[:countries].keys.each do |name|
86
+ countries.keys.each do |name|
74
87
  v4mod = config[:ipv4] ? name.to_s.upcase + 'v4' : 'nil'
75
88
  v6mod = config[:ipv6] ? name.to_s.upcase + 'v6' : 'nil'
76
89
  write_method file, name, v4mod, v6mod
@@ -78,21 +91,43 @@ module Geolocal
78
91
  file.write "end\n\n"
79
92
 
80
93
  status " writing "
81
- results.each do |name, body|
82
- status "#{name} "
83
- write_ranges file, modname, name, body
94
+ results.each do |name, ranges|
95
+ coalesced = coalesce_ranges(ranges)
96
+ status "#{name}-#{ranges.length - coalesced.length} "
97
+ write_ranges file, modname, name, coalesced
84
98
  end
85
99
  status "\n"
86
100
  end
87
101
 
88
102
 
103
+ def coalesce_ranges ranges
104
+ ranges = ranges.sort_by { |r| r.min }
105
+
106
+ uniques = []
107
+ lastr = ranges.shift
108
+ uniques << lastr if lastr
109
+
110
+ ranges.each do |thisr|
111
+ if lastr.last >= thisr.first - 1
112
+ lastr = lastr.first..[thisr.last, lastr.last].max
113
+ uniques[-1] = lastr
114
+ else
115
+ lastr = thisr
116
+ uniques << lastr
117
+ end
118
+ end
119
+
120
+ uniques
121
+ end
122
+
123
+
89
124
  def write_header file, modname
90
125
  file.write <<EOL
91
126
  # This file is autogenerated by the Geolocal gem
92
127
 
93
128
  module #{modname}
94
129
 
95
- def self.search address, family=nil, v4module, v6module
130
+ def self.search address, family, v4module, v6module
96
131
  address = IPAddr.new(address) if address.is_a?(String)
97
132
  family = address.family unless family
98
133
  num = address.to_i
@@ -117,10 +152,11 @@ EOL
117
152
  EOL
118
153
  end
119
154
 
120
- def write_ranges file, modname, name, body
155
+ def write_ranges file, modname, name, ranges
121
156
  file.write <<EOL
122
157
  #{modname}::#{name} = [
123
- #{body}]
158
+ #{ranges.join(",\n")}
159
+ ]
124
160
 
125
161
  EOL
126
162
  end
@@ -68,6 +68,14 @@ class Geolocal::Provider::DB_IP < Geolocal::Provider::Base
68
68
  "#{(@current_byte/1024/elapsed).round(1)} KB/sec\n"
69
69
  end
70
70
 
71
+ # a bit of debugging code to print all non-matched country codes. should be deleted one day.
72
+ def check_country_codes(countries, row)
73
+ @known_codes ||= countries.reduce(Set.new) { |a,(_,v)| a.merge v; a }
74
+ unless @known_codes.include?(row[2])
75
+ puts "#{row[2]}: #{row[0]}..#{row[1]}"
76
+ end
77
+ end
78
+
71
79
  def read_ranges countries
72
80
  status "computing ranges\n"
73
81
 
@@ -84,6 +92,7 @@ class Geolocal::Provider::DB_IP < Geolocal::Provider::Base
84
92
  match_count += 1
85
93
  yield name, row[0], row[1]
86
94
  end
95
+ # check_country_codes(countries, row)
87
96
  end
88
97
  end
89
98
  end
@@ -1,3 +1,3 @@
1
1
  module Geolocal
2
- VERSION = "0.6.2"
2
+ VERSION = "0.8"
3
3
  end
@@ -1,4 +1,14 @@
1
- require './config/geolocal'
1
+ # Provides geolocal's rake tasks.
2
+
3
+ # we use this file by default
4
+ config='config/geolocal'
5
+
6
+ # but you can specify the config file on the command line:
7
+ # `rake geolocal config=contrib/continents`
8
+ config=ENV['config'] if ENV['config']
9
+ puts "loading geolocal configuration from #{config}"
10
+ require './'+config
11
+
2
12
 
3
13
  namespace :geolocal do
4
14
  desc "Downloads the most recent geocoding information"
@@ -0,0 +1,181 @@
1
+ require 'spec_helper'
2
+ require 'geolocal/provider/base'
3
+
4
+
5
+ describe Geolocal::Provider::Base do
6
+ let(:it) { described_class }
7
+ let(:provider) { it.new }
8
+
9
+
10
+ describe '#add_to_results' do
11
+ it 'adds a v4 address to the results' do
12
+ result = { 'USv4'=>[] }
13
+ expect(
14
+ provider.add_to_results(result, 'US', '192.168.1.3', '192.168.1.4')
15
+ ).to eq 'USv4'
16
+ expect(result).to eq({ "USv4" => [3232235779..3232235780] })
17
+ end
18
+
19
+ it 'adds a v6 address to the results' do
20
+ result = { 'USv6'=>[] }
21
+ expect(
22
+ provider.add_to_results(result, 'US', '2001:400::', '2001:404::')
23
+ ).to eq 'USv6'
24
+ # wow, rspec bug? this expectation causes rspec to enter an infinite loop
25
+ # expect(result).to eq({ "USv6" => ["3232235779..3232235780,\n"] })
26
+ expect(result).to eq({ "USv6" =>
27
+ [42540569291614257367232052214305390592..42540569608526907424289402588481191936] })
28
+ end
29
+
30
+ it 'complains if given a bad range' do
31
+ expect {
32
+ provider.add_to_results({}, 'US', '192.168.1.5', '192.168.1.4')
33
+ }.to raise_error(/wrong order: 192.168.1.5\.\.192.168.1.4/)
34
+ end
35
+
36
+ it 'complains if given an illegal address' do
37
+ expect {
38
+ provider.add_to_results({}, 'US', 'dog', 'cat')
39
+ }.to raise_error(/invalid address/)
40
+ end
41
+
42
+ it 'complains if given non-matching addresses' do
43
+ expect {
44
+ provider.add_to_results({}, 'US', '192.168.1.5', '2001:400::')
45
+ }.to raise_error(/must be in the same address family/)
46
+ end
47
+ end
48
+
49
+
50
+ describe '#countries' do
51
+ it 'preprocesses the countries' do
52
+ Geolocal.configure do |config|
53
+ config.countries = { ua: :UA, na: ['MX', 'CA', :US] }
54
+ end
55
+
56
+ expect(provider.countries).to eq({ 'na' => Set['CA', 'MX', 'US'], 'ua' => Set['UA'] })
57
+ end
58
+
59
+ it 'preprocesses countries with an odd name' do
60
+ Geolocal.configure do |config|
61
+ config.countries = { 'U s-a': 'US', 'Mex': 'MX' }
62
+ end
63
+
64
+ expect(provider.countries).to eq({ 'mex' => Set['MX'], 'u_s_a' => Set['US'] })
65
+ end
66
+
67
+ it 'refuses invalid identifiers' do
68
+ Geolocal.configure do |config|
69
+ config.countries = { '1nation': 'US' }
70
+ end
71
+
72
+ expect { provider.countries }.to raise_error(/invalid identifier/)
73
+ end
74
+ end
75
+
76
+
77
+ describe '#coalesce_ranges' do
78
+ it 'can coalesce some ranges' do
79
+ expect(provider.coalesce_ranges([1..2, 3..4])).to eq [1..4]
80
+ expect(provider.coalesce_ranges([8..9, 6..7])).to eq [6..9]
81
+ expect(provider.coalesce_ranges([1..2, 4..5])).to eq [1..2, 4..5]
82
+ expect(provider.coalesce_ranges([7..9, 0..2])).to eq [0..2, 7..9]
83
+ expect(provider.coalesce_ranges([1..1, 2..2])).to eq [1..2]
84
+ expect(provider.coalesce_ranges([3..3, 1..1])).to eq [1..1, 3..3]
85
+ expect(provider.coalesce_ranges([1..2, 3..4, 2..6, 6..8, 8..9])).to eq [1..9]
86
+ end
87
+
88
+ it 'can coalesce some oddball cases' do
89
+ expect(provider.coalesce_ranges([])).to eq []
90
+ expect(provider.coalesce_ranges([1..1])).to eq [1..1]
91
+ end
92
+
93
+ it 'can coalesce some questionable ranges' do
94
+ expect(provider.coalesce_ranges([1..2, 2..4])).to eq [1..4]
95
+ expect(provider.coalesce_ranges([1..8, 2..9])).to eq [1..9]
96
+ expect(provider.coalesce_ranges([2..4, 1..2])).to eq [1..4]
97
+ expect(provider.coalesce_ranges([2..9, 1..8])).to eq [1..9]
98
+ end
99
+ end
100
+
101
+
102
+ describe 'generating' do
103
+ let(:example_results) { {
104
+ 'USv4' => [0..16777215, 34603520..34604031, 34605568..34606591],
105
+ 'USv6' => [0..42540528726795050063891204319802818559,
106
+ 42540569291614257367232052214305390592..42540570559264857595461453711008595967]
107
+ } }
108
+
109
+ before do
110
+ Geolocal.configure do |config|
111
+ config.countries = { 'US': 'US' }
112
+ end
113
+ end
114
+
115
+ it 'can generate both ipv4 and ipv6' do
116
+ Geolocal.configure do |config|
117
+ config.module = 'Geolocal_v4v6'
118
+ end
119
+
120
+ io = StringIO.new
121
+ provider.output io, example_results
122
+ expect(io.string).to include '0..42540528726795050063891204319802818559'
123
+ expect(io.string).to include '34605568..34606591'
124
+
125
+ eval io.string
126
+ expect(Geolocal_v4v6.in_us? '2.16.13.255').to eq true
127
+ expect(Geolocal_v4v6.in_us? IPAddr.new('2.16.13.255')).to eq true
128
+ expect(Geolocal_v4v6.in_us? 34606591, Socket::AF_INET).to eq true
129
+ expect(Geolocal_v4v6.in_us? 34606592, Socket::AF_INET).to eq nil
130
+
131
+ expect(Geolocal_v4v6.in_us? '2001:400::').to eq true
132
+ expect(Geolocal_v4v6.in_us? IPAddr.new('2001:400::')).to eq true
133
+ expect(Geolocal_v4v6.in_us? 42540570559264857595461453711008595967, Socket::AF_INET6).to eq true
134
+ expect(Geolocal_v4v6.in_us? 42540570559264857595461453711008595968, Socket::AF_INET6).to eq nil
135
+ end
136
+
137
+ it 'can turn off ipv4' do
138
+ Geolocal.configure do |config|
139
+ config.ipv4 = false
140
+ config.module = 'Geolocal_v6'
141
+ end
142
+
143
+ io = StringIO.new
144
+ provider.output io, example_results.tap { |h| h.delete('USv4') }
145
+ expect(io.string).to include '0..42540528726795050063891204319802818559'
146
+ expect(io.string).not_to include '34605568..34606591'
147
+
148
+ eval io.string
149
+ expect{ Geolocal_v6.in_us? '2.16.13.255' }.to raise_error(/ipv4 was not compiled in/)
150
+ expect( Geolocal_v6.in_us? '2001:400::' ).to eq true
151
+ end
152
+
153
+ it 'can turn off ipv6' do
154
+ Geolocal.configure do |config|
155
+ config.ipv6 = false
156
+ config.module = 'Geolocal_v4'
157
+ end
158
+
159
+ io = StringIO.new
160
+ provider.output io, example_results.tap { |h| h.delete('USv6') }
161
+ expect(io.string).to include '34605568..34606591'
162
+ expect(io.string).not_to include '0..42540528726795050063891204319802818559'
163
+
164
+ eval io.string
165
+ expect{ Geolocal_v4.in_us? '2001:400::' }.to raise_error(/ipv6 was not compiled in/)
166
+ expect( Geolocal_v4.in_us? '2.16.13.255' ).to eq true
167
+ end
168
+
169
+ it 'can turn off both ipv4 and ipv6' do
170
+ Geolocal.configure do |config|
171
+ config.ipv4 = false
172
+ config.ipv6 = false
173
+ end
174
+
175
+ io = StringIO.new
176
+ provider.output io, example_results.tap { |h| h.delete('USv4'); h.delete('USv6') }
177
+ expect(io.string).not_to include '34605568..34606591'
178
+ expect(io.string).not_to include '0..42540528726795050063891204319802818559'
179
+ end
180
+ end
181
+ end
@@ -61,7 +61,7 @@ describe Geolocal::Provider::DB_IP do
61
61
 
62
62
  module Geolocal
63
63
 
64
- def self.search address, family=nil, v4module, v6module
64
+ def self.search address, family, v4module, v6module
65
65
  address = IPAddr.new(address) if address.is_a?(String)
66
66
  family = address.family unless family
67
67
  num = address.to_i
@@ -98,30 +98,30 @@ EOL
98
98
 
99
99
  it 'can generate countries from a csv' do
100
100
  example_output = <<EOL
101
- def self.in_us? address, family=nil
102
- search address, family, USv4, USv6
103
- end
104
-
105
101
  def self.in_au? address, family=nil
106
102
  search address, family, AUv4, AUv6
107
103
  end
108
104
 
105
+ def self.in_us? address, family=nil
106
+ search address, family, USv4, USv6
107
+ end
108
+
109
109
  end
110
110
 
111
- Geolocal::USv4 = [
112
- 0..16777215,
111
+ Geolocal::AUv4 = [
112
+ 16777216..16777471
113
113
  ]
114
114
 
115
- Geolocal::USv6 = [
116
- 55854460156896106951106838613354086400..55854460790721407065221539361705689087,
115
+ Geolocal::AUv6 = [
116
+ 55832834671488781931518904937387917312..55832834671488781949965649011097468927
117
117
  ]
118
118
 
119
- Geolocal::AUv4 = [
120
- 16777216..16777471,
119
+ Geolocal::USv4 = [
120
+ 0..16777215
121
121
  ]
122
122
 
123
- Geolocal::AUv6 = [
124
- 55832834671488781931518904937387917312..55832834671488781949965649011097468927,
123
+ Geolocal::USv6 = [
124
+ 55854460156896106951106838613354086400..55854460790721407065221539361705689087
125
125
  ]
126
126
 
127
127
  EOL
@@ -133,22 +133,22 @@ EOL
133
133
 
134
134
  it 'can generate countries from a csv when ipv6 is turned off' do
135
135
  example_output = <<EOL
136
- def self.in_us? address, family=nil
137
- search address, family, USv4, nil
138
- end
139
-
140
136
  def self.in_au? address, family=nil
141
137
  search address, family, AUv4, nil
142
138
  end
143
139
 
140
+ def self.in_us? address, family=nil
141
+ search address, family, USv4, nil
142
+ end
143
+
144
144
  end
145
145
 
146
- Geolocal::USv4 = [
147
- 0..16777215,
146
+ Geolocal::AUv4 = [
147
+ 16777216..16777471
148
148
  ]
149
149
 
150
- Geolocal::AUv4 = [
151
- 16777216..16777471,
150
+ Geolocal::USv4 = [
151
+ 0..16777215
152
152
  ]
153
153
 
154
154
  EOL
@@ -161,22 +161,22 @@ EOL
161
161
 
162
162
  it 'can generate countries from a csv when ipv4 is turned off' do
163
163
  example_output = <<EOL
164
- def self.in_us? address, family=nil
165
- search address, family, nil, USv6
166
- end
167
-
168
164
  def self.in_au? address, family=nil
169
165
  search address, family, nil, AUv6
170
166
  end
171
167
 
168
+ def self.in_us? address, family=nil
169
+ search address, family, nil, USv6
170
+ end
171
+
172
172
  end
173
173
 
174
- Geolocal::USv6 = [
175
- 55854460156896106951106838613354086400..55854460790721407065221539361705689087,
174
+ Geolocal::AUv6 = [
175
+ 55832834671488781931518904937387917312..55832834671488781949965649011097468927
176
176
  ]
177
177
 
178
- Geolocal::AUv6 = [
179
- 55832834671488781931518904937387917312..55832834671488781949965649011097468927,
178
+ Geolocal::USv6 = [
179
+ 55854460156896106951106838613354086400..55854460790721407065221539361705689087
180
180
  ]
181
181
 
182
182
  EOL
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geolocal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: '0.8'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Bronson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-05 00:00:00.000000000 Z
11
+ date: 2015-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -82,7 +82,12 @@ files:
82
82
  - README.md
83
83
  - Rakefile
84
84
  - config/geolocal.rb
85
+ - contrib/array-vs-range-benchmark.rb
86
+ - contrib/continents.rb
85
87
  - geolocal.gemspec
88
+ - lib/generators/geolocal/USAGE
89
+ - lib/generators/geolocal/geolocal_generator.rb
90
+ - lib/generators/geolocal/templates/geolocal.rb
86
91
  - lib/geolocal.rb
87
92
  - lib/geolocal/configuration.rb
88
93
  - lib/geolocal/provider/base.rb
@@ -91,10 +96,10 @@ files:
91
96
  - lib/geolocal/railtie.rb
92
97
  - lib/geolocal/version.rb
93
98
  - lib/tasks/geolocal.rake
94
- - spec/configuration_spec.rb
95
99
  - spec/data/dbip-country.csv.gz
96
- - spec/provider/base_spec.rb
97
- - spec/provider/db_ip_spec.rb
100
+ - spec/geolocal/configuration_spec.rb
101
+ - spec/geolocal/provider/base_spec.rb
102
+ - spec/geolocal/provider/db_ip_spec.rb
98
103
  - spec/spec_helper.rb
99
104
  homepage: http://github.com/bronson/geolocal
100
105
  licenses:
@@ -121,8 +126,8 @@ signing_key:
121
126
  specification_version: 4
122
127
  summary: Generates plain Ruby if statements to geocode IP addresses
123
128
  test_files:
124
- - spec/configuration_spec.rb
125
129
  - spec/data/dbip-country.csv.gz
126
- - spec/provider/base_spec.rb
127
- - spec/provider/db_ip_spec.rb
130
+ - spec/geolocal/configuration_spec.rb
131
+ - spec/geolocal/provider/base_spec.rb
132
+ - spec/geolocal/provider/db_ip_spec.rb
128
133
  - spec/spec_helper.rb
@@ -1,86 +0,0 @@
1
- require 'spec_helper'
2
- require 'geolocal/provider/base'
3
-
4
-
5
- describe Geolocal::Provider::Base do
6
- let(:it) { described_class }
7
- let(:provider) { it.new }
8
-
9
- let(:example_results) { {
10
- 'USv4' => "0..16777215,\n34603520..34604031,\n34605568..34606591,\n",
11
- 'USv6' => "0..42540528726795050063891204319802818559,\n" +
12
- "42540569291614257367232052214305390592..42540570559264857595461453711008595967,\n"
13
- } }
14
-
15
- before do
16
- Geolocal.configure do |config|
17
- config.countries = { 'us': 'US' }
18
- end
19
- end
20
-
21
- it 'can generate both ipv4 and ipv6' do
22
- Geolocal.configure do |config|
23
- config.module = 'Geolocal_v4v6'
24
- end
25
-
26
- io = StringIO.new
27
- provider.output io, example_results
28
- expect(io.string).to include '0..42540528726795050063891204319802818559'
29
- expect(io.string).to include '34605568..34606591'
30
-
31
- eval io.string
32
- expect(Geolocal_v4v6.in_us? '2.16.13.255').to eq true
33
- expect(Geolocal_v4v6.in_us? IPAddr.new('2.16.13.255')).to eq true
34
- expect(Geolocal_v4v6.in_us? 34606591, Socket::AF_INET).to eq true
35
- expect(Geolocal_v4v6.in_us? 34606592, Socket::AF_INET).to eq nil
36
-
37
- expect(Geolocal_v4v6.in_us? '2001:400::').to eq true
38
- expect(Geolocal_v4v6.in_us? IPAddr.new('2001:400::')).to eq true
39
- expect(Geolocal_v4v6.in_us? 42540570559264857595461453711008595967, Socket::AF_INET6).to eq true
40
- expect(Geolocal_v4v6.in_us? 42540570559264857595461453711008595968, Socket::AF_INET6).to eq nil
41
- end
42
-
43
- it 'can turn off ipv4' do
44
- Geolocal.configure do |config|
45
- config.ipv4 = false
46
- config.module = 'Geolocal_v6'
47
- end
48
-
49
- io = StringIO.new
50
- provider.output io, example_results.tap { |h| h.delete('USv4') }
51
- expect(io.string).to include '0..42540528726795050063891204319802818559'
52
- expect(io.string).not_to include '34605568..34606591'
53
-
54
- eval io.string
55
- expect{ Geolocal_v6.in_us? '2.16.13.255' }.to raise_error(/ipv4 was not compiled in/)
56
- expect( Geolocal_v6.in_us? '2001:400::' ).to eq true
57
- end
58
-
59
- it 'can turn off ipv6' do
60
- Geolocal.configure do |config|
61
- config.ipv6 = false
62
- config.module = 'Geolocal_v4'
63
- end
64
-
65
- io = StringIO.new
66
- provider.output io, example_results.tap { |h| h.delete('USv6') }
67
- expect(io.string).to include '34605568..34606591'
68
- expect(io.string).not_to include '0..42540528726795050063891204319802818559'
69
-
70
- eval io.string
71
- expect{ Geolocal_v4.in_us? '2001:400::' }.to raise_error(/ipv6 was not compiled in/)
72
- expect( Geolocal_v4.in_us? '2.16.13.255' ).to eq true
73
- end
74
-
75
- it 'can turn off both ipv4 and ipv6' do
76
- Geolocal.configure do |config|
77
- config.ipv4 = false
78
- config.ipv6 = false
79
- end
80
-
81
- io = StringIO.new
82
- provider.output io, example_results.tap { |h| h.delete('USv4'); h.delete('USv6') }
83
- expect(io.string).not_to include '34605568..34606591'
84
- expect(io.string).not_to include '0..42540528726795050063891204319802818559'
85
- end
86
- end