geogov 0.0.1 → 0.0.3
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 +5 -0
- data/lib/geogov/geo_stack.rb +135 -134
- data/lib/geogov/providers/mapit.rb +12 -2
- data/test/geogov_test.rb +8 -0
- data/test/test_helper.rb +2 -6
- metadata +38 -82
data/lib/geogov.rb
CHANGED
@@ -13,9 +13,14 @@ require 'geogov/providers/dracos_gazetteer'
|
|
13
13
|
module Geogov
|
14
14
|
|
15
15
|
def self.provider_for(method, instance)
|
16
|
+
unless instance.respond_to?(method)
|
17
|
+
raise ArgumentError.new("#{instance.class} doesn't respond to #{method}")
|
18
|
+
end
|
19
|
+
|
16
20
|
caching_instance = SimpleCache.new(instance)
|
17
21
|
@@methods ||= {}
|
18
22
|
@@methods[method] = caching_instance
|
23
|
+
|
19
24
|
unless self.methods().include?(method)
|
20
25
|
dispatcher = <<-EOS
|
21
26
|
def #{method}(*args, &block)
|
data/lib/geogov/geo_stack.rb
CHANGED
@@ -1,140 +1,141 @@
|
|
1
1
|
module Geogov
|
2
2
|
class GeoStack
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
4
|
+
attr_accessor :ward, :council, :nation, :country, :wmc, :lat, :lon, :friendly_name
|
5
|
+
attr_reader :postcode, :fuzzy_point
|
6
|
+
|
7
|
+
def initialize(&block)
|
8
|
+
if block_given?
|
9
|
+
yield self
|
10
|
+
else
|
11
|
+
self.fuzzy_point = calculate_fuzzy_point
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def calculate_fuzzy_point
|
16
|
+
if self.lat and self.lon
|
17
|
+
return FuzzyPoint.new(self.lat, self.lon, :point)
|
18
|
+
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
20
|
+
if self.postcode
|
21
|
+
district = postcode.split(" ")[0]
|
22
|
+
district_centre = Geogov.centre_of_district(district)
|
23
|
+
if district_centre
|
24
|
+
return FuzzyPoint.new(district_centre["lat"],district_centre["lon"],:postcode_district)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if self.country
|
29
|
+
country_centre = Geogov.centre_of_country(self.country)
|
30
|
+
if country_centre
|
31
|
+
return FuzzyPoint.new(country_centre["lat"],country_centre["lon"],:country)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
FuzzyPoint.new(0,0,:planet)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.new_from_ip(ip_address)
|
39
|
+
remote_location = Geogov.remote_location(ip_address)
|
40
|
+
new() do |gs|
|
41
|
+
if remote_location
|
42
|
+
gs.country = remote_location['country']
|
43
|
+
end
|
44
|
+
gs.fuzzy_point = gs.calculate_fuzzy_point
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.new_from_hash(hash)
|
49
|
+
new() do |gs|
|
50
|
+
gs.set_fields(hash)
|
51
|
+
unless hash['fuzzy_point']
|
52
|
+
raise ArgumentError, "fuzzy point required"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_hash
|
58
|
+
{
|
59
|
+
:fuzzy_point => self.fuzzy_point.to_hash,
|
60
|
+
:postcode => self.postcode,
|
61
|
+
:ward => self.ward,
|
62
|
+
:council => self.council,
|
63
|
+
:nation => self.nation,
|
64
|
+
:country => self.country,
|
65
|
+
:wmc => self.wmc,
|
66
|
+
:friendly_name => self.friendly_name
|
67
|
+
}.select {|k,v| !(v.nil?) }
|
68
|
+
end
|
69
|
+
|
70
|
+
def update(hash)
|
71
|
+
self.class.new() do |empty|
|
72
|
+
full_postcode = hash['postcode']
|
73
|
+
empty.set_fields(hash)
|
74
|
+
if has_valid_lat_lon(hash)
|
75
|
+
empty.fetch_missing_fields_for_coords(hash['lat'], hash['lon'])
|
76
|
+
elsif full_postcode
|
77
|
+
empty.fetch_missing_fields_for_postcode(full_postcode)
|
78
|
+
end
|
79
|
+
empty.fuzzy_point = empty.calculate_fuzzy_point
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def has_valid_lat_lon(hash)
|
81
84
|
return (hash['lon'] and hash['lat'] and hash['lon'] != "" and hash['lat'] != "")
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
85
|
+
end
|
86
|
+
|
87
|
+
def fetch_missing_fields_for_postcode(postcode)
|
88
|
+
if matches = postcode.match(POSTCODE_REGEXP)
|
89
|
+
self.country = "UK"
|
90
|
+
fields = Geogov.areas_for_stack_from_postcode(postcode)
|
91
|
+
if fields
|
92
|
+
lat_lon = fields[:point]
|
93
|
+
if lat_lon
|
94
|
+
self.friendly_name = Geogov.nearest_place_name(lat_lon['lat'],lat_lon['lon'])
|
95
|
+
end
|
96
|
+
set_fields(fields.select {|k,v| k != :point})
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
97
100
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
end
|
140
|
-
end
|
101
|
+
def fetch_missing_fields_for_coords(lat, lon)
|
102
|
+
self.friendly_name = Geogov.nearest_place_name(lat, lon)
|
103
|
+
fields = Geogov.areas_for_stack_from_coords(lat, lon)
|
104
|
+
if ['England', 'Scotland', 'Northern Ireland', 'Wales'].include?(fields[:nation])
|
105
|
+
self.country = 'UK'
|
106
|
+
set_fields(fields.select {|k,v| k != :point})
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_fields(hash)
|
111
|
+
hash.each do |geo, value|
|
112
|
+
setter = (geo.to_s+"=").to_sym
|
113
|
+
if self.respond_to?(setter)
|
114
|
+
unless value == ""
|
115
|
+
self.send(setter,value)
|
116
|
+
end
|
117
|
+
else
|
118
|
+
raise ArgumentError, "geo type '#{geo}' is not a valid geo type"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
self
|
122
|
+
end
|
123
|
+
|
124
|
+
def fuzzy_point=(point)
|
125
|
+
if point.is_a?(Hash)
|
126
|
+
@fuzzy_point = FuzzyPoint.new(point["lat"],point["lon"],point["accuracy"])
|
127
|
+
else
|
128
|
+
@fuzzy_point = point
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
POSTCODE_REGEXP = /^([A-Z]{1,2}[0-9R][0-9A-Z]?)\s*([0-9])[ABD-HJLNP-UW-Z]{2}(:?\s+)?$/i
|
133
|
+
SECTOR_POSTCODE_REGEXP = /^([A-Z]{1,2}[0-9R][0-9A-Z]?)\s*([0-9])(:?\s+)?$/i
|
134
|
+
|
135
|
+
def postcode=(postcode)
|
136
|
+
if (matches = (postcode.match(POSTCODE_REGEXP) || postcode.match(SECTOR_POSTCODE_REGEXP)))
|
137
|
+
@postcode = matches[1]+" "+matches[2]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -20,6 +20,7 @@ module Geogov
|
|
20
20
|
}
|
21
21
|
url_path = "#{base_url}#{url}"
|
22
22
|
url_path += "/#{params.join("/")}" if params.length > 0
|
23
|
+
url_path += ".json"
|
23
24
|
return url_path
|
24
25
|
end
|
25
26
|
|
@@ -39,6 +40,11 @@ module Geogov
|
|
39
40
|
def respond_to?(sym)
|
40
41
|
valid_mapit_methods.include?(sym) || super(sym)
|
41
42
|
end
|
43
|
+
|
44
|
+
def lat_lon_from_postcode(postcode)
|
45
|
+
areas = areas_for_stack_from_postcode(postcode)
|
46
|
+
areas[:point]
|
47
|
+
end
|
42
48
|
|
43
49
|
# Borrowed heavily from mapit's pylib/postcodes/views.py with some amendments based on
|
44
50
|
# pylib/mapit/areas/models.py
|
@@ -62,7 +68,9 @@ module Geogov
|
|
62
68
|
if level
|
63
69
|
level = level.downcase.to_sym
|
64
70
|
results[level] = [] unless results[level]
|
65
|
-
|
71
|
+
level_info = area_info.select { |k,v| ["name","id","type"].include?(k) }
|
72
|
+
level_info['ons'] = area_info['codes']['ons'] if area_info['codes'] && area_info['codes']['ons']
|
73
|
+
results[level] << level_info
|
66
74
|
results[:nation] = area_info['country_name'] if results[:nation].nil?
|
67
75
|
end
|
68
76
|
end
|
@@ -83,7 +91,9 @@ module Geogov
|
|
83
91
|
area_info = query['areas'][id.to_s]
|
84
92
|
level = typ.downcase.to_sym
|
85
93
|
results[level] = [] unless results[level]
|
86
|
-
|
94
|
+
level_info = area_info.select { |k,v| ["name","id","type"].include?(k) }
|
95
|
+
level_info['ons'] = area_info['codes']['ons'] if area_info['codes'] && area_info['codes']['ons']
|
96
|
+
results[level] << level_info
|
87
97
|
results[:nation] = area_info['country_name'] if results[:nation].nil?
|
88
98
|
end
|
89
99
|
end
|
data/test/geogov_test.rb
CHANGED
@@ -28,6 +28,14 @@ class GovspeakTest < Test::Unit::TestCase
|
|
28
28
|
assert_equal 0, stack.fuzzy_point.lat
|
29
29
|
assert_equal :planet, stack.fuzzy_point.accuracy
|
30
30
|
end
|
31
|
+
|
32
|
+
test "raises an exception if provider doesn't support required method" do
|
33
|
+
assert_raises(ArgumentError) {
|
34
|
+
Geogov.configure do |g|
|
35
|
+
g.provider_for :lat_lon_from_postcode, stub
|
36
|
+
end
|
37
|
+
}
|
38
|
+
end
|
31
39
|
|
32
40
|
test "reconstructed stack rejects unknown params" do
|
33
41
|
assert_raises(ArgumentError) {
|
data/test/test_helper.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
$:.unshift(File.expand_path("../lib")) unless $:.include?(File.expand_path("../lib"))
|
2
2
|
|
3
|
-
require 'bundler'
|
4
|
-
Bundler.setup :default, :development, :test
|
5
|
-
|
6
3
|
require 'test/unit'
|
4
|
+
require 'mocha'
|
5
|
+
require 'geogov'
|
7
6
|
|
8
7
|
class Test::Unit::TestCase
|
9
8
|
class << self
|
@@ -16,6 +15,3 @@ class Test::Unit::TestCase
|
|
16
15
|
end
|
17
16
|
end
|
18
17
|
end
|
19
|
-
|
20
|
-
require 'mocha'
|
21
|
-
require 'geogov'
|
metadata
CHANGED
@@ -1,81 +1,47 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: geogov
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 1
|
10
|
-
version: 0.0.1
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Ben Griffiths
|
9
|
+
- James Stewart
|
14
10
|
autorequire:
|
15
11
|
bindir: bin
|
16
12
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
13
|
+
date: 2011-12-08 00:00:00.000000000Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
22
16
|
name: rake
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
17
|
+
requirement: &70342818099700 !ruby/object:Gem::Requirement
|
25
18
|
none: false
|
26
|
-
requirements:
|
19
|
+
requirements:
|
27
20
|
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
- 8
|
33
|
-
- 0
|
34
|
-
version: 0.8.0
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.9.0
|
35
23
|
type: :development
|
36
|
-
version_requirements: *id001
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: mocha
|
39
24
|
prerelease: false
|
40
|
-
|
25
|
+
version_requirements: *70342818099700
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: mocha
|
28
|
+
requirement: &70342818099000 !ruby/object:Gem::Requirement
|
41
29
|
none: false
|
42
|
-
requirements:
|
30
|
+
requirements:
|
43
31
|
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
hash: 59
|
46
|
-
segments:
|
47
|
-
- 0
|
48
|
-
- 9
|
49
|
-
- 0
|
32
|
+
- !ruby/object:Gem::Version
|
50
33
|
version: 0.9.0
|
51
34
|
type: :development
|
52
|
-
version_requirements: *id002
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: rspec
|
55
35
|
prerelease: false
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
- - ~>
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
hash: 27
|
62
|
-
segments:
|
63
|
-
- 2
|
64
|
-
- 5
|
65
|
-
- 0
|
66
|
-
version: 2.5.0
|
67
|
-
type: :development
|
68
|
-
version_requirements: *id003
|
69
|
-
description: Geolocation and utilities for single domain
|
70
|
-
email:
|
36
|
+
version_requirements: *70342818099000
|
37
|
+
description: Geolocation and utilities for UK Government single domain
|
38
|
+
email:
|
71
39
|
- ben@alphagov.co.uk
|
40
|
+
- jystewart@gmail.com
|
72
41
|
executables: []
|
73
|
-
|
74
42
|
extensions: []
|
75
|
-
|
76
43
|
extra_rdoc_files: []
|
77
|
-
|
78
|
-
files:
|
44
|
+
files:
|
79
45
|
- lib/geogov/fuzzy_point.rb
|
80
46
|
- lib/geogov/geo_stack.rb
|
81
47
|
- lib/geogov/providers/dracos_gazetteer.rb
|
@@ -90,40 +56,30 @@ files:
|
|
90
56
|
- Rakefile
|
91
57
|
- test/geogov_test.rb
|
92
58
|
- test/test_helper.rb
|
93
|
-
has_rdoc: true
|
94
59
|
homepage: http://github.com/alphagov/geogov
|
95
60
|
licenses: []
|
96
|
-
|
97
61
|
post_install_message:
|
98
62
|
rdoc_options: []
|
99
|
-
|
100
|
-
require_paths:
|
63
|
+
require_paths:
|
101
64
|
- lib
|
102
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
66
|
none: false
|
104
|
-
requirements:
|
105
|
-
- -
|
106
|
-
- !ruby/object:Gem::Version
|
107
|
-
|
108
|
-
|
109
|
-
- 0
|
110
|
-
version: "0"
|
111
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
72
|
none: false
|
113
|
-
requirements:
|
114
|
-
- -
|
115
|
-
- !ruby/object:Gem::Version
|
116
|
-
|
117
|
-
segments:
|
118
|
-
- 0
|
119
|
-
version: "0"
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
120
77
|
requirements: []
|
121
|
-
|
122
78
|
rubyforge_project:
|
123
|
-
rubygems_version: 1.
|
79
|
+
rubygems_version: 1.8.10
|
124
80
|
signing_key:
|
125
81
|
specification_version: 3
|
126
|
-
summary: Geolocation and utilities for single domain
|
127
|
-
test_files:
|
82
|
+
summary: Geolocation and utilities for UK Government single domain
|
83
|
+
test_files:
|
128
84
|
- test/geogov_test.rb
|
129
85
|
- test/test_helper.rb
|