geolocal 0.6.2 → 0.8

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.
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