posty 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/LICENCE +5 -0
- data/README.rdoc +52 -0
- data/Rakefile +19 -0
- data/VERSION +1 -0
- data/bin/posty-init +86 -0
- data/lib/posty.rb +49 -0
- metadata +103 -0
data/.gitignore
ADDED
data/LICENCE
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
Copyright © 2010, The Dextrous Web
|
2
|
+
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
4
|
+
|
5
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
= Posty
|
2
|
+
|
3
|
+
Simple geolocation gem that stores the database locally.
|
4
|
+
|
5
|
+
= Getting started
|
6
|
+
|
7
|
+
gem install posty
|
8
|
+
|
9
|
+
To download mySociety's mirror of the Code-Point Open in WGS84 format, and create a database from it, and store that inside the gem (you may not need the sudo):
|
10
|
+
|
11
|
+
sudo posty-init -g
|
12
|
+
|
13
|
+
This takes about 8 minutes for me, and leaves me with a database of approximately 157M.
|
14
|
+
|
15
|
+
If you don't want the database being stored in your gem, run something like this instead:
|
16
|
+
|
17
|
+
posty-init -d database.sqlite3
|
18
|
+
|
19
|
+
Then, in Ruby:
|
20
|
+
|
21
|
+
require 'posty'
|
22
|
+
posty = Posty.new
|
23
|
+
postcode = posty.postcode('SE1 1EN') # space is optional, as is capitalisation
|
24
|
+
|
25
|
+
p postcode.postcode
|
26
|
+
p [postcode.latitude, postcode.longitude]
|
27
|
+
p postcode.county
|
28
|
+
|
29
|
+
If the database isn't in the gem, you'll need to tell it where to find it:
|
30
|
+
|
31
|
+
posty = Posty.new('database.sqlite3')
|
32
|
+
|
33
|
+
To make things even easier, there's a class method too (which accepts the database as the second parameter):
|
34
|
+
|
35
|
+
Posty.postcode('SE1 1EN')
|
36
|
+
|
37
|
+
= Notes
|
38
|
+
|
39
|
+
The table contains the following columns, extracted from the WGS84 edition of Code-Point Open:
|
40
|
+
|
41
|
+
* postcode
|
42
|
+
* quality
|
43
|
+
* latitude
|
44
|
+
* longitude
|
45
|
+
* country
|
46
|
+
* nhs_region
|
47
|
+
* nhs_health_authority
|
48
|
+
* county
|
49
|
+
* district
|
50
|
+
* ward
|
51
|
+
|
52
|
+
It does not contain eastings and northings.
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'jeweler'
|
5
|
+
Jeweler::Tasks.new do |gem|
|
6
|
+
gem.name = 'posty'
|
7
|
+
gem.summary = %Q{Simple geolocation gem that stores the database locally}
|
8
|
+
gem.description = %Q{}
|
9
|
+
gem.email = 'tom@thedextrousweb.com'
|
10
|
+
gem.homepage = 'http://github.com/dxw/posty'
|
11
|
+
gem.authors = ['Tom Adams']
|
12
|
+
gem.add_dependency 'sqlite3-ruby'
|
13
|
+
gem.add_dependency 'choice'
|
14
|
+
gem.add_dependency 'fastercsv'
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
data/bin/posty-init
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'posty'
|
4
|
+
require 'sqlite3'
|
5
|
+
require 'tmpdir'
|
6
|
+
require 'choice'
|
7
|
+
require 'fastercsv'
|
8
|
+
require 'fileutils'
|
9
|
+
|
10
|
+
codepoint_wgs = 'http://parlvid.mysociety.org:81/os/codepo_gb_wgs84.zip'
|
11
|
+
|
12
|
+
Choice.options do
|
13
|
+
option :database do
|
14
|
+
short '-d'
|
15
|
+
long '--database=SQLITE'
|
16
|
+
desc 'The database to create and put data into.'
|
17
|
+
end
|
18
|
+
option :gem do
|
19
|
+
short '-g'
|
20
|
+
long '--gem'
|
21
|
+
desc 'Install the database into the gem (may require sudo).'
|
22
|
+
end
|
23
|
+
option :codepoint do
|
24
|
+
short '-c'
|
25
|
+
long '--codepoint=ZIPFILE'
|
26
|
+
desc 'Existing (WGS84-formatted) codepoint zip file.'
|
27
|
+
default nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
database = Choice.choices[:database]
|
32
|
+
if Choice.choices[:gem]
|
33
|
+
FileUtils.mkdir_p File.dirname(Posty.gem_database)
|
34
|
+
database = Posty.gem_database
|
35
|
+
elsif database.nil?
|
36
|
+
STDERR.puts 'Requires either -d or -g option.'
|
37
|
+
exit 2
|
38
|
+
end
|
39
|
+
codepoint = Choice.choices[:codepoint]
|
40
|
+
|
41
|
+
# Die if db already exists
|
42
|
+
if File.exist? database
|
43
|
+
STDERR.puts 'Database already exists. Not overwriting.'
|
44
|
+
exit 1
|
45
|
+
end
|
46
|
+
|
47
|
+
Dir.mktmpdir do |dir|
|
48
|
+
# Download wgs84 dump from mySociety
|
49
|
+
unless codepoint and File.exist? codepoint
|
50
|
+
`wget '#{codepoint_wgs}' -O '#{dir}/codepo_gb_wgs84.zip'`
|
51
|
+
codepoint = "#{dir}/codepo_gb_wgs84.zip"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Unzip
|
55
|
+
`unzip -d '#{dir}' '#{codepoint}'`
|
56
|
+
|
57
|
+
# Create database
|
58
|
+
STDERR.puts "Writing database to #{database}"
|
59
|
+
db = SQLite3::Database.new(database)
|
60
|
+
db.execute <<END
|
61
|
+
CREATE TABLE codepoint (postcode PRIMARY KEY, quality, latitude, longitude, country, nhs_region, nhs_health_authority, county, district, ward)
|
62
|
+
END
|
63
|
+
|
64
|
+
# Slurp CSV into SQLite
|
65
|
+
Dir.glob("#{dir}/data/CSV/*.csv").sort.each do |csv|
|
66
|
+
csv.match(/(\w+)\.csv$/)
|
67
|
+
STDERR.puts "Reading #{$1.upcase}"
|
68
|
+
|
69
|
+
db.transaction do |db|
|
70
|
+
|
71
|
+
FasterCSV.foreach(csv) do |row|
|
72
|
+
# Normalise postcode (strip the space)
|
73
|
+
norm_postcode = row[0].gsub(/[^\w\d]/,'').upcase
|
74
|
+
data = [norm_postcode]+row[1..-1]
|
75
|
+
|
76
|
+
db.execute <<END, *data
|
77
|
+
INSERT INTO codepoint VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
78
|
+
END
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
db.close
|
84
|
+
end
|
85
|
+
|
86
|
+
STDERR.puts 'Finished.'
|
data/lib/posty.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'sqlite3'
|
2
|
+
|
3
|
+
class PostCode
|
4
|
+
attr_reader :data
|
5
|
+
def initialize data
|
6
|
+
@data = {}
|
7
|
+
data.each_pair do |a,b|
|
8
|
+
@data[a] = b if a.is_a? String
|
9
|
+
end
|
10
|
+
|
11
|
+
@data['latitude'] = @data['latitude'].to_f
|
12
|
+
@data['longitude'] = @data['longitude'].to_f
|
13
|
+
end
|
14
|
+
|
15
|
+
%w[postcode quality latitude longitude country nhs_region nhs_health_authority county district ward].each do |m|
|
16
|
+
define_method(m) {@data[m]}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Posty
|
21
|
+
def initialize database = nil
|
22
|
+
if database.nil?
|
23
|
+
database = Posty.gem_database
|
24
|
+
unless File.exist? database
|
25
|
+
raise IOError, "No database found in gem. Have you run posty-init -g (possibly with sudo)?"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
unless File.exist? database
|
30
|
+
raise IOError, "No database found at #{database}. Have you run posty-init -d '#{database}'?"
|
31
|
+
end
|
32
|
+
|
33
|
+
@db = SQLite3::Database.new(database)
|
34
|
+
@db.results_as_hash = true
|
35
|
+
end
|
36
|
+
|
37
|
+
def postcode code
|
38
|
+
code = code.gsub(/[^\w\d]/,'').upcase
|
39
|
+
PostCode.new(@db.get_first_row('SELECT * FROM codepoint WHERE postcode = ?', code))
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.gem_database
|
43
|
+
"#{File.dirname(__FILE__)}/posty/codepointopen.sqlite3"
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.postcode code, database = nil
|
47
|
+
Posty.new(database).postcode(code)
|
48
|
+
end
|
49
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: posty
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Tom Adams
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-04-13 00:00:00 +01:00
|
18
|
+
default_executable: posty-init
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: sqlite3-ruby
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: choice
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
41
|
+
version: "0"
|
42
|
+
type: :runtime
|
43
|
+
version_requirements: *id002
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: fastercsv
|
46
|
+
prerelease: false
|
47
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
type: :runtime
|
55
|
+
version_requirements: *id003
|
56
|
+
description: ""
|
57
|
+
email: tom@thedextrousweb.com
|
58
|
+
executables:
|
59
|
+
- posty-init
|
60
|
+
extensions: []
|
61
|
+
|
62
|
+
extra_rdoc_files:
|
63
|
+
- README.rdoc
|
64
|
+
files:
|
65
|
+
- .gitignore
|
66
|
+
- LICENCE
|
67
|
+
- README.rdoc
|
68
|
+
- Rakefile
|
69
|
+
- VERSION
|
70
|
+
- bin/posty-init
|
71
|
+
- lib/posty.rb
|
72
|
+
has_rdoc: true
|
73
|
+
homepage: http://github.com/dxw/posty
|
74
|
+
licenses: []
|
75
|
+
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options:
|
78
|
+
- --charset=UTF-8
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
requirements: []
|
96
|
+
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.3.6
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: Simple geolocation gem that stores the database locally
|
102
|
+
test_files: []
|
103
|
+
|