uk_postcode 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +90 -42
- data/lib/uk_postcode/version.rb +1 -1
- data/test/samples_test.rb +12 -25
- data/test/test_helper.rb +4 -0
- data/test/uk_postcode_test.rb +135 -140
- metadata +38 -61
- data/test/samples/code_point_open_20101105.list +0 -1696041
- data/test/samples/code_point_open_20101105.list.bz2 +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fd5d3327b3f2fff64453bb32cbf18941c6e668ed
|
4
|
+
data.tar.gz: 9e8d9284064d002eb6b004ed1fbd0d5779b9a9aa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: efa1121b17ba18e5d1c33ddd6a8d0ee7a239e1c1baa35a1699400e5e2f3892542636d585fe597bd66be3fa7a4f0148ec824d5a335430a1dd06daf13b6887325e
|
7
|
+
data.tar.gz: 26f43a092dce9d1f706cf36eee76af39d076b988af4d08ff581ee7ac21c84465f8a2f8d34b570e7021b68038f9e1558bf6c28e21b3c42bd18c221a7526122b31
|
data/README.md
CHANGED
@@ -1,66 +1,114 @@
|
|
1
|
-
uk_postcode
|
2
|
-
===========
|
1
|
+
# uk_postcode
|
3
2
|
|
4
|
-
UK postcode parsing and validation for Ruby
|
3
|
+
UK postcode parsing and validation for Ruby for writing friendly software.
|
5
4
|
|
6
|
-
|
7
|
-
-----
|
5
|
+
Features:
|
8
6
|
|
9
|
-
|
7
|
+
* Handles errors with `I`/`1` and `O`/`0`.
|
8
|
+
* Does not require postcodes to contain spaces.
|
9
|
+
* Normalises postcodes (e.g. `wiaiaa` to `W1A 1AA`).
|
10
|
+
* Parses full postcodes or outcodes (`W1A`)
|
11
|
+
* Allows extraction of fields within postcode.
|
12
|
+
* Validated against 2.5 million postcodes in England, Wales, Scotland, Northern
|
13
|
+
Ireland, the Channel Islands, and the Isle of Man.
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
require "uk_postcode"
|
19
|
+
```
|
10
20
|
|
11
21
|
Validate and extract sections of a full postcode:
|
12
22
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
23
|
+
```ruby
|
24
|
+
pc = UKPostcode.new("W1A 2AB")
|
25
|
+
pc.valid? #=> true
|
26
|
+
pc.full? #=> true
|
27
|
+
pc.outcode #=> "W1A"
|
28
|
+
pc.incode #=> "2AB"
|
29
|
+
pc.area #=> "W"
|
30
|
+
pc.district #=> "1A"
|
31
|
+
pc.sector #=> "2"
|
32
|
+
pc.unit #=> "AB"
|
33
|
+
```
|
22
34
|
|
23
35
|
Or of a partial postcode:
|
24
36
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
37
|
+
```ruby
|
38
|
+
pc = UKPostcode.new("W1A")
|
39
|
+
pc.valid? #=> true
|
40
|
+
pc.full? #=> false
|
41
|
+
pc.outcode #=> "W1A"
|
42
|
+
pc.incode #=> nil
|
43
|
+
pc.area #=> "W"
|
44
|
+
pc.district #=> "1A"
|
45
|
+
pc.sector #=> nil
|
46
|
+
pc.unit #=> nil
|
47
|
+
```
|
34
48
|
|
35
|
-
Normalise postcodes:
|
49
|
+
Normalise postcodes with `normalize` (or just `norm`):
|
36
50
|
|
37
|
-
|
51
|
+
```ruby
|
52
|
+
UKPostcode.new("w1a1aa").normalize #=> "W1A 1AA"
|
53
|
+
```
|
38
54
|
|
39
55
|
Fix mistakes with IO/10:
|
40
56
|
|
41
|
-
|
42
|
-
|
43
|
-
|
57
|
+
```ruby
|
58
|
+
pc = UKPostcode.new("WIA OAA")
|
59
|
+
pc.outcode #=> "W1A"
|
60
|
+
pc.incode #=> "0AA"
|
61
|
+
```
|
62
|
+
|
63
|
+
## Gem?
|
44
64
|
|
45
|
-
|
46
|
-
|
65
|
+
```sh
|
66
|
+
$ gem install uk_postcode
|
67
|
+
```
|
47
68
|
|
48
|
-
|
69
|
+
## Testing
|
49
70
|
|
50
|
-
|
51
|
-
|
71
|
+
To run the test suite:
|
72
|
+
|
73
|
+
```sh
|
74
|
+
$ rake
|
75
|
+
```
|
52
76
|
|
53
77
|
The full list of UK postcodes is not included in the repository due to its
|
54
78
|
size.
|
79
|
+
Additional sample files under `test/samples` will automatically be used.
|
80
|
+
|
81
|
+
The format of each line in a sample file must be `OOOOIII` or `OOO III` (where
|
82
|
+
`O` = outcode, `I` = incode), e.g.:
|
83
|
+
|
84
|
+
```
|
85
|
+
AB1 0AA
|
86
|
+
BT109AH
|
87
|
+
```
|
88
|
+
|
89
|
+
You can obtain lists of postcodes by processing various datasets available
|
90
|
+
from [mySociety][mys].
|
91
|
+
|
92
|
+
### Code-Point Open
|
93
|
+
|
94
|
+
This does not include postcodes for Northern Ireland, the Channel Islands,
|
95
|
+
or the Isle of Man.
|
96
|
+
|
97
|
+
```sh
|
98
|
+
$ cut -c 2-8 Data/CSV/*.csv | \
|
99
|
+
sort -uV > test/samples/large/code_point_open.list
|
100
|
+
```
|
55
101
|
|
56
|
-
|
57
|
-
[Code-Point® Open data set][cpo] from Ordnance Survey, and to extract and
|
58
|
-
transform it:
|
102
|
+
### ONS Postcode Directory
|
59
103
|
|
60
|
-
|
61
|
-
|
104
|
+
This includes postcodes for the whole UK as well as the Channel Islands and the
|
105
|
+
Isle of Man.
|
106
|
+
It also includes some defunct postcodes, most notably the NPT outcode, which
|
107
|
+
must be filtered out.
|
62
108
|
|
63
|
-
|
109
|
+
```sh
|
110
|
+
$ cut -c 2-8 ONSPD_*.csv | grep '[A-Z]' | grep -v ^NPT | \
|
111
|
+
sort -uV > test/samples/large/onspd.list
|
112
|
+
```
|
64
113
|
|
65
|
-
[
|
66
|
-
[dl]: https://github.com/threedaymonk/uk_postcode/downloads
|
114
|
+
[mys]: http://parlvid.mysociety.org/os/
|
data/lib/uk_postcode/version.rb
CHANGED
data/test/samples_test.rb
CHANGED
@@ -1,30 +1,17 @@
|
|
1
|
-
|
2
|
-
require "test/unit"
|
3
|
-
require "shoulda"
|
1
|
+
require_relative "./test_helper"
|
4
2
|
require "uk_postcode"
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
should "be valid for each line in sample file" do
|
19
|
-
@file.each_line do |line|
|
20
|
-
next if line =~ /^#|^$/
|
21
|
-
outcode = line[0,4].strip
|
22
|
-
incode = line[4,4].strip
|
23
|
-
postcode = UKPostcode.new(outcode + incode)
|
24
|
-
assert postcode.valid?, "'#{outcode} #{incode}' should be valid"
|
25
|
-
assert_equal outcode, postcode.outcode, "incorrect outcode for '#{outcode} #{incode}'"
|
26
|
-
assert_equal incode, postcode.incode, "incorrect incode for '#{outcode} #{incode}'"
|
27
|
-
end
|
4
|
+
describe "Sample files" do
|
5
|
+
Dir[File.expand_path("../samples/**/*.list", __FILE__)].each do |path|
|
6
|
+
it "should be valid for each line in #{File.basename(path, ".list")}" do
|
7
|
+
open(path).each_line do |line|
|
8
|
+
next if line =~ /^#|^$/
|
9
|
+
outcode = line[0,4].strip
|
10
|
+
incode = line[4,3].strip
|
11
|
+
postcode = UKPostcode.new(outcode + incode)
|
12
|
+
postcode.must_be :valid?
|
13
|
+
postcode.outcode.must_equal outcode
|
14
|
+
postcode.incode.must_equal incode
|
28
15
|
end
|
29
16
|
end
|
30
17
|
end
|
data/test/test_helper.rb
ADDED
data/test/uk_postcode_test.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
-
|
2
|
-
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
3
|
-
require "test/unit"
|
4
|
-
require "shoulda"
|
1
|
+
require_relative "./test_helper"
|
5
2
|
require "uk_postcode"
|
6
3
|
|
7
|
-
|
4
|
+
describe UKPostcode do
|
8
5
|
|
9
6
|
VALID_SAMPLES = [
|
10
7
|
%w[A 9 9 AA], %w[A 99 9 AA], %w[AA 9 9 AA], %w[AA 99 9 AA], %w[A 9A 9 AA],
|
@@ -13,122 +10,122 @@ class UKPostcodeTest < Test::Unit::TestCase
|
|
13
10
|
%w[EX 1 1 AE], %w[TQ 1 1 AG]
|
14
11
|
]
|
15
12
|
|
16
|
-
{ "full samples with spaces" => lambda{ |a,b,c,d| [[a, b, " ", c, d].join, [a, b, c, d]] },
|
17
|
-
"full samples without spaces" => lambda{ |a,b,c,d| [[a, b, c, d].join, [a, b, c, d]] },
|
13
|
+
{ "full samples with spaces" => lambda{ |(a,b,c,d)| [[a, b, " ", c, d].join, [a, b, c, d]] },
|
14
|
+
"full samples without spaces" => lambda{ |(a,b,c,d)| [[a, b, c, d].join, [a, b, c, d]] },
|
18
15
|
}.each do |desc, mapping|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
should
|
25
|
-
|
26
|
-
|
16
|
+
describe desc do
|
17
|
+
let(:samples) {
|
18
|
+
VALID_SAMPLES.map(&mapping)
|
19
|
+
}
|
20
|
+
|
21
|
+
it "should all be valid" do
|
22
|
+
samples.each do |sample, _|
|
23
|
+
UKPostcode.new(sample).must_be :valid?
|
27
24
|
end
|
28
25
|
end
|
29
26
|
|
30
|
-
should
|
31
|
-
|
32
|
-
|
27
|
+
it "should all be full" do
|
28
|
+
samples.each do |sample, _|
|
29
|
+
UKPostcode.new(sample).must_be :full?
|
33
30
|
end
|
34
31
|
end
|
35
32
|
|
36
|
-
should
|
37
|
-
|
38
|
-
|
33
|
+
it "should extract outcodes" do
|
34
|
+
samples.each do |sample, parts|
|
35
|
+
UKPostcode.new(sample).outcode.must_equal parts[0] + parts[1]
|
39
36
|
end
|
40
37
|
end
|
41
38
|
|
42
|
-
should
|
43
|
-
|
44
|
-
|
39
|
+
it "should extract incodes" do
|
40
|
+
samples.each do |sample, parts|
|
41
|
+
UKPostcode.new(sample).incode.must_equal parts[2] + parts[3]
|
45
42
|
end
|
46
43
|
end
|
47
44
|
|
48
|
-
should
|
49
|
-
|
50
|
-
|
45
|
+
it "should extract area" do
|
46
|
+
samples.each do |sample, parts|
|
47
|
+
UKPostcode.new(sample).area.must_equal parts[0]
|
51
48
|
end
|
52
49
|
end
|
53
50
|
|
54
|
-
should
|
55
|
-
|
56
|
-
|
51
|
+
it "should extract district" do
|
52
|
+
samples.each do |sample, parts|
|
53
|
+
UKPostcode.new(sample).district.must_equal parts[1]
|
57
54
|
end
|
58
55
|
end
|
59
56
|
|
60
|
-
should
|
61
|
-
|
62
|
-
|
57
|
+
it "should extract sector" do
|
58
|
+
samples.each do |sample, parts|
|
59
|
+
UKPostcode.new(sample).sector.must_equal parts[2]
|
63
60
|
end
|
64
61
|
end
|
65
62
|
|
66
|
-
should
|
67
|
-
|
68
|
-
|
63
|
+
it "should extract unit" do
|
64
|
+
samples.each do |sample, parts|
|
65
|
+
UKPostcode.new(sample).unit.must_equal parts[3]
|
69
66
|
end
|
70
67
|
end
|
71
68
|
|
72
|
-
should
|
73
|
-
|
69
|
+
it "should be the same when normalised" do
|
70
|
+
samples.each do |sample, parts|
|
74
71
|
expected = [parts[0], parts[1], " ", parts[2], parts[3]].join
|
75
|
-
|
72
|
+
UKPostcode.new(sample).norm.must_equal expected
|
76
73
|
end
|
77
74
|
end
|
78
75
|
end
|
79
76
|
end
|
80
77
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
78
|
+
describe "outcode samples" do
|
79
|
+
let(:samples) {
|
80
|
+
VALID_SAMPLES.map{ |a,b,c,d| [a, b].join }
|
81
|
+
}
|
85
82
|
|
86
|
-
should
|
87
|
-
|
88
|
-
|
83
|
+
it "should all be valid" do
|
84
|
+
samples.each do |sample|
|
85
|
+
UKPostcode.new(sample).must_be :valid?
|
89
86
|
end
|
90
87
|
end
|
91
88
|
|
92
|
-
should
|
93
|
-
|
94
|
-
|
89
|
+
it "should not be full" do
|
90
|
+
samples.each do |sample|
|
91
|
+
UKPostcode.new(sample).wont_be :full?
|
95
92
|
end
|
96
93
|
end
|
97
94
|
|
98
|
-
should
|
99
|
-
|
100
|
-
|
95
|
+
it "should keep outcode unchanged" do
|
96
|
+
samples.each do |sample|
|
97
|
+
UKPostcode.new(sample).outcode.must_equal sample
|
101
98
|
end
|
102
99
|
end
|
103
100
|
|
104
|
-
should
|
105
|
-
|
106
|
-
|
101
|
+
it "should have nil incode" do
|
102
|
+
samples.each do |sample|
|
103
|
+
UKPostcode.new(sample).incode.must_be_nil
|
107
104
|
end
|
108
105
|
end
|
109
106
|
|
110
|
-
should
|
111
|
-
|
112
|
-
|
107
|
+
it "should be the same when normalised" do
|
108
|
+
samples.each do |sample|
|
109
|
+
UKPostcode.new(sample).norm.must_equal sample
|
113
110
|
end
|
114
111
|
end
|
115
112
|
end
|
116
113
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
114
|
+
describe "when the postcode is supplied in lower case" do
|
115
|
+
let(:postcode) {
|
116
|
+
UKPostcode.new("w1a 1aa")
|
117
|
+
}
|
121
118
|
|
122
|
-
should
|
123
|
-
|
119
|
+
it "should extract outcode in upper case" do
|
120
|
+
postcode.outcode.must_equal "W1A"
|
124
121
|
end
|
125
122
|
|
126
|
-
should
|
127
|
-
|
123
|
+
it "should extract incode in upper case" do
|
124
|
+
postcode.incode.must_equal "1AA"
|
128
125
|
end
|
129
126
|
|
130
|
-
should
|
131
|
-
|
127
|
+
it "should be valid" do
|
128
|
+
postcode.must_be :valid?
|
132
129
|
end
|
133
130
|
end
|
134
131
|
|
@@ -137,147 +134,145 @@ class UKPostcodeTest < Test::Unit::TestCase
|
|
137
134
|
"when the outcode is truncated" => "W",
|
138
135
|
"when the postcode is invalid" => "ABC DEFG"
|
139
136
|
}.each do |desc, sample|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
137
|
+
describe desc do
|
138
|
+
let(:postcode) {
|
139
|
+
UKPostcode.new(sample)
|
140
|
+
}
|
144
141
|
|
145
|
-
should
|
146
|
-
|
142
|
+
it "should not be valid" do
|
143
|
+
refute postcode.valid?
|
147
144
|
end
|
148
145
|
|
149
|
-
should
|
150
|
-
|
146
|
+
it "should not be full" do
|
147
|
+
refute postcode.full?
|
151
148
|
end
|
152
149
|
|
153
|
-
should
|
154
|
-
|
150
|
+
it "should return an empty string when normalised" do
|
151
|
+
postcode.norm.must_equal ""
|
155
152
|
end
|
156
153
|
|
157
|
-
should
|
158
|
-
|
154
|
+
it "should return nil for outcode" do
|
155
|
+
postcode.outcode.must_be_nil
|
159
156
|
end
|
160
157
|
|
161
|
-
should
|
162
|
-
|
158
|
+
it "should return nil for incode" do
|
159
|
+
postcode.incode.must_be_nil
|
163
160
|
end
|
164
161
|
end
|
165
162
|
end
|
166
163
|
|
167
|
-
|
168
|
-
should
|
169
|
-
|
164
|
+
describe "when used as a string" do
|
165
|
+
it "should normalise spacing when no spacing has been used in the input" do
|
166
|
+
UKPostcode.new("W1A1AA").norm.must_equal "W1A 1AA"
|
170
167
|
end
|
171
168
|
|
172
|
-
should
|
173
|
-
|
169
|
+
it "should normalise spacing when too much spacing has been used in the input" do
|
170
|
+
UKPostcode.new("W1A 1AA").norm.must_equal "W1A 1AA"
|
174
171
|
end
|
175
172
|
|
176
|
-
should
|
177
|
-
|
173
|
+
it "should convert case" do
|
174
|
+
UKPostcode.new("w1a 1aa").norm.must_equal "W1A 1AA"
|
178
175
|
end
|
179
176
|
|
180
|
-
should
|
181
|
-
|
177
|
+
it "should ignore a missing incode" do
|
178
|
+
UKPostcode.new("W1A").norm.must_equal "W1A"
|
182
179
|
end
|
183
180
|
|
184
|
-
should
|
185
|
-
|
181
|
+
it "should trim whitespace from start and end of the string" do
|
182
|
+
UKPostcode.new(" W1A 1AA ").norm.must_equal "W1A 1AA"
|
186
183
|
end
|
187
184
|
end
|
188
185
|
|
189
|
-
should
|
186
|
+
it "should return original input for to_s" do
|
190
187
|
["W1A1AA", "w1a 1aa", "W1A"].each do |s|
|
191
|
-
|
192
|
-
assert_equal s, postcode.to_s
|
188
|
+
UKPostcode.new(s).to_s.must_equal s
|
193
189
|
end
|
194
190
|
end
|
195
191
|
|
196
|
-
should
|
192
|
+
it "should return original input for to_str" do
|
197
193
|
["W1A1AA", "w1a 1aa", "W1A"].each do |s|
|
198
|
-
|
199
|
-
assert_equal s, postcode.to_str
|
194
|
+
UKPostcode.new(s).to_str.must_equal s
|
200
195
|
end
|
201
196
|
end
|
202
197
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
198
|
+
describe "when letters are used instead of digits" do
|
199
|
+
describe "in a full postcode" do
|
200
|
+
let(:postcode) {
|
201
|
+
UKPostcode.new("SWIA OPW")
|
202
|
+
}
|
208
203
|
|
209
|
-
should
|
210
|
-
|
204
|
+
it "should be valid" do
|
205
|
+
postcode.must_be :valid?
|
211
206
|
end
|
212
207
|
|
213
|
-
should
|
214
|
-
|
208
|
+
it "should be full" do
|
209
|
+
postcode.must_be :full?
|
215
210
|
end
|
216
211
|
|
217
|
-
should
|
218
|
-
|
212
|
+
it "should normalise to digits" do
|
213
|
+
postcode.norm.must_equal "SW1A 0PW"
|
219
214
|
end
|
220
215
|
end
|
221
216
|
end
|
222
217
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
218
|
+
describe "when digits are used instead of letters" do
|
219
|
+
describe "in a full postcode" do
|
220
|
+
let(:postcode) {
|
221
|
+
UKPostcode.new("0X1 0AB")
|
222
|
+
}
|
228
223
|
|
229
|
-
should
|
230
|
-
|
224
|
+
it "should be valid" do
|
225
|
+
postcode.must_be :valid?
|
231
226
|
end
|
232
227
|
|
233
|
-
should
|
234
|
-
|
228
|
+
it "should be full" do
|
229
|
+
postcode.must_be :full?
|
235
230
|
end
|
236
231
|
|
237
|
-
should
|
238
|
-
|
232
|
+
it "should normalise to letters" do
|
233
|
+
postcode.norm.must_equal "OX1 0AB"
|
239
234
|
end
|
240
235
|
end
|
241
236
|
end
|
242
237
|
|
243
|
-
|
238
|
+
describe "single-letter area code" do
|
244
239
|
%w[B E G L M N S W].each do |area|
|
245
|
-
|
246
|
-
should
|
240
|
+
describe area do
|
241
|
+
it "should not convert 1 to I in two-digit outcode" do
|
247
242
|
outcode = area + "11"
|
248
243
|
postcode = UKPostcode.new(outcode)
|
249
|
-
|
250
|
-
|
244
|
+
postcode.area.must_equal area
|
245
|
+
postcode.outcode.must_equal outcode
|
251
246
|
end
|
252
247
|
|
253
|
-
should
|
248
|
+
it "should not convert 1 to I in full postcode with space" do
|
254
249
|
outcode = area + "13"
|
255
250
|
postcode = UKPostcode.new(outcode + " 1AA")
|
256
|
-
|
257
|
-
|
251
|
+
postcode.area.must_equal area
|
252
|
+
postcode.outcode.must_equal outcode
|
258
253
|
end
|
259
254
|
|
260
|
-
should
|
255
|
+
it "should not convert 1 to I in full postcode without space" do
|
261
256
|
outcode = area + "13"
|
262
257
|
postcode = UKPostcode.new(outcode + "2AA")
|
263
|
-
|
264
|
-
|
258
|
+
postcode.area.must_equal area
|
259
|
+
postcode.outcode.must_equal outcode
|
265
260
|
end
|
266
261
|
end
|
267
262
|
end
|
268
263
|
end
|
269
264
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
265
|
+
describe "GIR 0AA" do
|
266
|
+
let(:norm) {
|
267
|
+
"GIR 0AA"
|
268
|
+
}
|
274
269
|
|
275
|
-
should
|
276
|
-
|
270
|
+
it "should stay as is if already normalised" do
|
271
|
+
UKPostcode.new(norm).norm.must_equal norm
|
277
272
|
end
|
278
273
|
|
279
|
-
should
|
280
|
-
|
274
|
+
it "should be normalised" do
|
275
|
+
UKPostcode.new("G1ROAA").norm.must_equal norm
|
281
276
|
end
|
282
277
|
end
|
283
278
|
end
|