geogov 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|