geogov 0.0.3 → 0.0.4
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/geogov.rb +26 -14
- data/lib/geogov/providers/mapit.rb +22 -19
- data/test/geogov_test.rb +41 -36
- metadata +7 -7
data/lib/geogov.rb
CHANGED
@@ -12,15 +12,18 @@ require 'geogov/providers/dracos_gazetteer'
|
|
12
12
|
|
13
13
|
module Geogov
|
14
14
|
|
15
|
+
class UnrecognizedLocationError < RuntimeError
|
16
|
+
end
|
17
|
+
|
15
18
|
def self.provider_for(method, instance)
|
16
19
|
unless instance.respond_to?(method)
|
17
20
|
raise ArgumentError.new("#{instance.class} doesn't respond to #{method}")
|
18
21
|
end
|
19
|
-
|
22
|
+
|
20
23
|
caching_instance = SimpleCache.new(instance)
|
21
24
|
@@methods ||= {}
|
22
25
|
@@methods[method] = caching_instance
|
23
|
-
|
26
|
+
|
24
27
|
unless self.methods().include?(method)
|
25
28
|
dispatcher = <<-EOS
|
26
29
|
def #{method}(*args, &block)
|
@@ -28,30 +31,39 @@ module Geogov
|
|
28
31
|
end
|
29
32
|
EOS
|
30
33
|
module_eval(dispatcher)
|
31
|
-
end
|
34
|
+
end
|
32
35
|
end
|
33
36
|
|
34
37
|
def self.configure
|
35
38
|
yield self
|
36
39
|
end
|
37
40
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
def lat_lon_from_postcode(postcode)
|
42
|
+
result = Mapit.new().lat_lon_from_postcode(postcode)
|
43
|
+
|
44
|
+
if result.nil?
|
45
|
+
raise UnrecognizedLocationError
|
46
|
+
end
|
47
|
+
|
48
|
+
result
|
49
|
+
end
|
50
|
+
|
51
|
+
provider_for :nearest_place_name, DracosGazetteer.new()
|
52
|
+
|
53
|
+
provider_for :lat_lon_to_country, Geonames.new()
|
54
|
+
provider_for :centre_of_country, Geonames.new()
|
42
55
|
|
43
|
-
provider_for :centre_of_district,
|
56
|
+
provider_for :centre_of_district, Mapit.new()
|
44
57
|
provider_for :areas_for_stack_from_postcode, Mapit.new()
|
45
|
-
provider_for :areas_for_stack_from_coords,
|
46
|
-
provider_for :lat_lon_from_postcode, Mapit.new()
|
58
|
+
provider_for :areas_for_stack_from_coords, Mapit.new()
|
47
59
|
|
48
|
-
provider_for :remote_location,
|
60
|
+
provider_for :remote_location, Hostip.new()
|
49
61
|
|
50
|
-
provider_for :map_img,
|
51
|
-
provider_for :map_href,
|
62
|
+
provider_for :map_img, Google.new()
|
63
|
+
provider_for :map_href, Google.new()
|
52
64
|
|
53
65
|
extend self
|
54
|
-
|
66
|
+
|
55
67
|
end
|
56
68
|
|
57
69
|
|
@@ -4,17 +4,17 @@ require 'uri'
|
|
4
4
|
module Geogov
|
5
5
|
|
6
6
|
class Mapit
|
7
|
-
|
7
|
+
|
8
8
|
class Method
|
9
|
-
def initialize(url,params = [])
|
9
|
+
def initialize(url, params = [])
|
10
10
|
@url = url
|
11
11
|
@params = params
|
12
12
|
end
|
13
13
|
|
14
14
|
def to_url(base_url)
|
15
15
|
url = "/#{@url}" unless /^\//.match(@url)
|
16
|
-
params = @params.map {|p|
|
17
|
-
p = p.join(",") if p.is_a?(Array)
|
16
|
+
params = @params.map { |p|
|
17
|
+
p = p.join(",") if p.is_a?(Array)
|
18
18
|
# Messy, but MapIt gets upset if you escape commas
|
19
19
|
CGI::escape(p).gsub('%2C', ',')
|
20
20
|
}
|
@@ -34,24 +34,26 @@ module Geogov
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def valid_mapit_methods
|
37
|
-
[:postcode
|
37
|
+
[:postcode, :areas, :area, :point, :generations]
|
38
38
|
end
|
39
39
|
|
40
40
|
def respond_to?(sym)
|
41
41
|
valid_mapit_methods.include?(sym) || super(sym)
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
def lat_lon_from_postcode(postcode)
|
45
45
|
areas = areas_for_stack_from_postcode(postcode)
|
46
46
|
areas[:point]
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
# Borrowed heavily from mapit's pylib/postcodes/views.py with some amendments based on
|
50
50
|
# pylib/mapit/areas/models.py
|
51
51
|
def translate_area_type_to_shortcut(area_type)
|
52
|
-
if ['COP','LBW','LGE','MTW','UTE','UTW','DIW'].include?(area_type)
|
52
|
+
if ['COP', 'LBW', 'LGE', 'MTW', 'UTE', 'UTW', 'DIW'].include?(area_type)
|
53
53
|
return 'ward'
|
54
54
|
elsif ['CTY', 'CED'].include?(area_type)
|
55
|
+
|
56
|
+
git
|
55
57
|
return 'council' # county
|
56
58
|
elsif ['DIS', 'LBO'].include?(area_type)
|
57
59
|
return 'council' # district
|
@@ -61,14 +63,14 @@ module Geogov
|
|
61
63
|
end
|
62
64
|
|
63
65
|
def areas_for_stack_from_coords(lat, lon)
|
64
|
-
query = self.point("4326", [lon,lat])
|
66
|
+
query = self.point("4326", [lon, lat])
|
65
67
|
results = {:point => {'lat' => lat, 'lon' => lon}}
|
66
|
-
query.each do |id,area_info|
|
68
|
+
query.each do |id, area_info|
|
67
69
|
level = translate_area_type_to_shortcut(area_info['type'])
|
68
70
|
if level
|
69
71
|
level = level.downcase.to_sym
|
70
72
|
results[level] = [] unless results[level]
|
71
|
-
level_info = area_info.select { |k,v| ["name","id","type"].include?(k) }
|
73
|
+
level_info = area_info.select { |k, v| ["name", "id", "type"].include?(k) }
|
72
74
|
level_info['ons'] = area_info['codes']['ons'] if area_info['codes'] && area_info['codes']['ons']
|
73
75
|
results[level] << level_info
|
74
76
|
results[:nation] = area_info['country_name'] if results[:nation].nil?
|
@@ -80,40 +82,41 @@ module Geogov
|
|
80
82
|
def areas_for_stack_from_postcode(postcode)
|
81
83
|
query = self.postcode(postcode)
|
82
84
|
results = {}
|
85
|
+
|
83
86
|
if query && query['shortcuts'] && query['areas']
|
84
|
-
query['shortcuts'].each do |typ,i|
|
87
|
+
query['shortcuts'].each do |typ, i|
|
85
88
|
if i.is_a? Hash
|
86
89
|
ids = i.values()
|
87
90
|
else
|
88
91
|
ids = [i]
|
89
92
|
end
|
90
93
|
ids.each do |id|
|
91
|
-
area_info =
|
94
|
+
area_info = query['areas'][id.to_s]
|
92
95
|
level = typ.downcase.to_sym
|
93
96
|
results[level] = [] unless results[level]
|
94
|
-
level_info = area_info.select { |k,v| ["name","id","type"].include?(k) }
|
97
|
+
level_info = area_info.select { |k, v| ["name", "id", "type"].include?(k) }
|
95
98
|
level_info['ons'] = area_info['codes']['ons'] if area_info['codes'] && area_info['codes']['ons']
|
96
99
|
results[level] << level_info
|
97
100
|
results[:nation] = area_info['country_name'] if results[:nation].nil?
|
98
101
|
end
|
99
102
|
end
|
100
|
-
lat,lon = query['wgs84_lat'],query['wgs84_lon']
|
103
|
+
lat, lon = query['wgs84_lat'], query['wgs84_lon']
|
101
104
|
results[:point] = {'lat' => lat, 'lon' => lon}
|
102
105
|
end
|
103
106
|
return results
|
104
107
|
end
|
105
|
-
|
108
|
+
|
106
109
|
def centre_of_district(district_postcode)
|
107
|
-
query = self.postcode("partial",district_postcode)
|
110
|
+
query = self.postcode("partial", district_postcode)
|
108
111
|
if query
|
109
|
-
lat,lon = query['wgs84_lat'],query['wgs84_lon']
|
112
|
+
lat, lon = query['wgs84_lat'], query['wgs84_lon']
|
110
113
|
return {'lat' => lat, 'lon' => lon}
|
111
114
|
end
|
112
115
|
end
|
113
116
|
|
114
117
|
def method_missing(method, *args, &block)
|
115
118
|
if valid_mapit_methods.include?(method)
|
116
|
-
Mapit::Method.new(method.to_s,args).call(@base)
|
119
|
+
Mapit::Method.new(method.to_s, args).call(@base)
|
117
120
|
else
|
118
121
|
super(method, *args, &block)
|
119
122
|
end
|
data/test/geogov_test.rb
CHANGED
@@ -1,72 +1,77 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class GovspeakTest < Test::Unit::TestCase
|
4
|
-
|
4
|
+
|
5
5
|
test "IP-located stack should have country" do
|
6
6
|
|
7
7
|
Geogov.configure do |g|
|
8
|
-
g.provider_for :centre_of_country, stub(:centre_of_country => {"lat"=>37,"lon"=>-96})
|
9
|
-
g.provider_for :remote_location,
|
8
|
+
g.provider_for :centre_of_country, stub(:centre_of_country => {"lat"=>37, "lon"=>-96})
|
9
|
+
g.provider_for :remote_location, stub(:remote_location => {'country' => 'US'})
|
10
10
|
end
|
11
11
|
|
12
12
|
stack = Geogov::GeoStack.new_from_ip('173.203.129.90')
|
13
|
-
assert_equal
|
13
|
+
assert_equal "US", stack.country
|
14
14
|
assert_in_delta stack.fuzzy_point.lon, -96, 0.5
|
15
15
|
assert_in_delta stack.fuzzy_point.lat, 37, 0.5
|
16
|
-
assert_equal
|
16
|
+
assert_equal :country, stack.fuzzy_point.accuracy
|
17
17
|
end
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
g.provider_for :remote_location, stub(:remote_location => nil)
|
23
|
-
end
|
24
|
-
|
25
|
-
stack = Geogov::GeoStack.new_from_ip('127.0.0.1')
|
26
|
-
assert_nil stack.country
|
27
|
-
assert_equal 0, stack.fuzzy_point.lon
|
28
|
-
assert_equal 0, stack.fuzzy_point.lat
|
29
|
-
assert_equal :planet, stack.fuzzy_point.accuracy
|
18
|
+
|
19
|
+
test "should be specific if no country available" do
|
20
|
+
Geogov.configure do |g|
|
21
|
+
g.provider_for :remote_location, stub(:remote_location => nil)
|
30
22
|
end
|
31
23
|
|
24
|
+
stack = Geogov::GeoStack.new_from_ip('127.0.0.1')
|
25
|
+
assert_nil stack.country
|
26
|
+
assert_equal 0, stack.fuzzy_point.lon
|
27
|
+
assert_equal 0, stack.fuzzy_point.lat
|
28
|
+
assert_equal :planet, stack.fuzzy_point.accuracy
|
29
|
+
end
|
30
|
+
|
32
31
|
test "raises an exception if provider doesn't support required method" do
|
33
|
-
assert_raises(ArgumentError) {
|
32
|
+
assert_raises(ArgumentError) {
|
34
33
|
Geogov.configure do |g|
|
35
34
|
g.provider_for :lat_lon_from_postcode, stub
|
36
|
-
end
|
35
|
+
end
|
37
36
|
}
|
38
37
|
end
|
39
|
-
|
38
|
+
|
39
|
+
test "raises an error if the supplied postcode is invalid" do
|
40
|
+
assert_raises(Geogov::UnrecognizedLocationError) {
|
41
|
+
Geogov.lat_lon_from_postcode("nowhere")
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
40
45
|
test "reconstructed stack rejects unknown params" do
|
41
|
-
|
42
|
-
|
43
|
-
|
46
|
+
assert_raises(ArgumentError) {
|
47
|
+
Geogov::GeoStack.new_from_hash("galaxy" => "Andromeda")
|
48
|
+
}
|
44
49
|
end
|
45
50
|
|
46
51
|
test "reconstructed stack should refuse creation if no fuzzy point" do
|
47
|
-
|
48
|
-
|
49
|
-
|
52
|
+
assert_raises(ArgumentError) {
|
53
|
+
Geogov::GeoStack.new_from_hash("country" => "US")
|
54
|
+
}
|
50
55
|
end
|
51
56
|
|
52
57
|
test "reconstructed stack should always truncate postcode" do
|
53
|
-
|
54
|
-
|
58
|
+
stack = Geogov::GeoStack.new_from_hash("postcode"=>"SE10 8UG", "country" => "UK", "fuzzy_point" => {"lat"=>"37", "lon"=>"-96", "accuracy"=>"postcode"})
|
59
|
+
assert_equal "SE10 8", stack.postcode
|
55
60
|
end
|
56
|
-
|
61
|
+
|
57
62
|
test "stack should not consider a postcode with trailing whitespace invalid" do
|
58
|
-
|
59
|
-
|
63
|
+
stack = Geogov::GeoStack.new_from_hash("postcode"=>"SE10 8UG ", "country" => "UK", "fuzzy_point" => {"lat"=>"37", "lon"=>"-96", "accuracy"=>"postcode"})
|
64
|
+
assert_equal "SE10 8", stack.postcode
|
60
65
|
end
|
61
66
|
|
62
67
|
test "stack should ignore invalid postcodes" do
|
63
|
-
|
64
|
-
|
68
|
+
stack = Geogov::GeoStack.new_from_hash("postcode"=>"NOTAPOSTCODE", "country" => "UK", "fuzzy_point" => {"lat"=>"37", "lon"=>"-96", "accuracy"=>"postcode"})
|
69
|
+
assert_nil stack.postcode
|
65
70
|
end
|
66
|
-
|
71
|
+
|
67
72
|
test "stack with country should have country accuracy" do
|
68
|
-
stack = Geogov::GeoStack.new_from_hash("country" => "US","fuzzy_point" => {"lat"=>"37","lon"=>"-96","accuracy"=>"country"})
|
73
|
+
stack = Geogov::GeoStack.new_from_hash("country" => "US", "fuzzy_point" => {"lat"=>"37", "lon"=>"-96", "accuracy"=>"country"})
|
69
74
|
assert_equal :country, stack.fuzzy_point.accuracy
|
70
75
|
end
|
71
|
-
|
76
|
+
|
72
77
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geogov
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-12-
|
13
|
+
date: 2011-12-20 00:00:00.000000000Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|
17
|
-
requirement: &
|
17
|
+
requirement: &70306547782860 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 0.9.0
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70306547782860
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: mocha
|
28
|
-
requirement: &
|
28
|
+
requirement: &70306547781900 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
@@ -33,7 +33,7 @@ dependencies:
|
|
33
33
|
version: 0.9.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *70306547781900
|
37
37
|
description: Geolocation and utilities for UK Government single domain
|
38
38
|
email:
|
39
39
|
- ben@alphagov.co.uk
|
@@ -76,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
76
|
version: '0'
|
77
77
|
requirements: []
|
78
78
|
rubyforge_project:
|
79
|
-
rubygems_version: 1.8.
|
79
|
+
rubygems_version: 1.8.12
|
80
80
|
signing_key:
|
81
81
|
specification_version: 3
|
82
82
|
summary: Geolocation and utilities for UK Government single domain
|