uk_postcode 0.0.1
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/README.md +34 -0
- data/Rakefile +44 -0
- data/lib/uk_postcode.rb +46 -0
- data/test/test_uk_postcode.rb +174 -0
- metadata +67 -0
data/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
uk_postcode
|
|
2
|
+
===========
|
|
3
|
+
|
|
4
|
+
UK postcode parsing and validation for Ruby.
|
|
5
|
+
|
|
6
|
+
Usage
|
|
7
|
+
-----
|
|
8
|
+
|
|
9
|
+
require "uk_postcode"
|
|
10
|
+
|
|
11
|
+
Validate and extract sections of a full postcode:
|
|
12
|
+
|
|
13
|
+
pc = UKPostcode.new("W1A 1AA")
|
|
14
|
+
pc.valid? #=> true
|
|
15
|
+
pc.full? #=> true
|
|
16
|
+
pc.outcode #=> "W1A"
|
|
17
|
+
pc.incode #=> "1AA"
|
|
18
|
+
|
|
19
|
+
Or of a partial postcode:
|
|
20
|
+
|
|
21
|
+
pc = UKPostcode.new("W1A")
|
|
22
|
+
pc.valid? #=> true
|
|
23
|
+
pc.full? #=> false
|
|
24
|
+
pc.outcode #=> "W1A"
|
|
25
|
+
pc.incode #=> nil
|
|
26
|
+
|
|
27
|
+
Normalise postcodes:
|
|
28
|
+
|
|
29
|
+
UKPostcode.new("w1a1aa").to_str #=> "W1A 1AA"
|
|
30
|
+
|
|
31
|
+
Gem?
|
|
32
|
+
----
|
|
33
|
+
|
|
34
|
+
gem install uk_postcode
|
data/Rakefile
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require "rubygems"
|
|
2
|
+
require "rake/gempackagetask"
|
|
3
|
+
require "rake/testtask"
|
|
4
|
+
|
|
5
|
+
task :default => [:test]
|
|
6
|
+
|
|
7
|
+
Rake::TestTask.new("test") do |t|
|
|
8
|
+
t.libs << "test"
|
|
9
|
+
t.pattern = "test/**/test_*.rb"
|
|
10
|
+
t.verbose = true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
task :default => :test
|
|
14
|
+
|
|
15
|
+
require "rake/testtask"
|
|
16
|
+
Rake::TestTask.new do |t|
|
|
17
|
+
t.libs << "test"
|
|
18
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
|
19
|
+
t.verbose = true
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
spec = Gem::Specification.new do |s|
|
|
23
|
+
s.name = "uk_postcode"
|
|
24
|
+
s.version = "0.0.1"
|
|
25
|
+
s.summary = "UK postcode parsing and validation"
|
|
26
|
+
s.author = "Paul Battley"
|
|
27
|
+
s.email = "pbattley@gmail.com"
|
|
28
|
+
|
|
29
|
+
s.has_rdoc = true
|
|
30
|
+
|
|
31
|
+
s.files = %w(Rakefile README.md) + Dir.glob("{bin,test,lib}/**/*")
|
|
32
|
+
s.executables = FileList["bin/**"].map { |f| File.basename(f) }
|
|
33
|
+
|
|
34
|
+
s.require_paths = ["lib"]
|
|
35
|
+
|
|
36
|
+
s.add_development_dependency("thoughtbot-shoulda")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
|
40
|
+
pkg.gem_spec = spec
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
desc 'Clear out generated packages'
|
|
44
|
+
task :clean => [:clobber_package]
|
data/lib/uk_postcode.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class UKPostcode
|
|
2
|
+
RE_OUTCODE = /[A-Z]{1,2}[0-9R][0-9A-Z]?/
|
|
3
|
+
RE_INCODE = /[0-9][ABD-HJLNP-UW-Z]{2}/
|
|
4
|
+
RE_OUTCODE_ONLY = /\A(#{RE_OUTCODE})\Z/
|
|
5
|
+
RE_FULL = /\A(#{RE_OUTCODE}) ?(#{RE_INCODE})\Z/
|
|
6
|
+
|
|
7
|
+
attr_reader :raw
|
|
8
|
+
|
|
9
|
+
# Initialise a new UKPostcode instance from the given postcode string
|
|
10
|
+
#
|
|
11
|
+
def initialize(postcode_as_string)
|
|
12
|
+
@raw = postcode_as_string.upcase
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Returns true if the postcode is a valid full postcode (e.g. W1A 1AA) or outcode (e.g. W1A)
|
|
16
|
+
#
|
|
17
|
+
def valid?
|
|
18
|
+
raw.match(RE_FULL) || raw.match(RE_OUTCODE_ONLY)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Returns true if the postcode is a valid full postcode (e.g. W1A 1AA)
|
|
22
|
+
#
|
|
23
|
+
def full?
|
|
24
|
+
raw.match(RE_FULL)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# The left-hand part of the postcode, e.g. W1A 1AA -> W1A
|
|
28
|
+
#
|
|
29
|
+
def outcode
|
|
30
|
+
raw[RE_FULL, 1] || raw[RE_OUTCODE_ONLY]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# The right-hand part of the postcode, e.g. W1A 1AA -> 1AA
|
|
34
|
+
#
|
|
35
|
+
def incode
|
|
36
|
+
raw[RE_FULL, 2]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Render the postcode as a normalised string, i.e. in upper case and with spacing.
|
|
40
|
+
# Returns an empty string if the postcode is not valid.
|
|
41
|
+
#
|
|
42
|
+
def to_str
|
|
43
|
+
[outcode, incode].compact.join(" ")
|
|
44
|
+
end
|
|
45
|
+
alias_method :to_s, :to_str
|
|
46
|
+
end
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
|
2
|
+
require "test/unit"
|
|
3
|
+
require "shoulda"
|
|
4
|
+
require "uk_postcode"
|
|
5
|
+
|
|
6
|
+
class UKPostcodeTest < Test::Unit::TestCase
|
|
7
|
+
|
|
8
|
+
VALID_SAMPLES = [ "A9 9AA", "A99 9AA", "AA9 9AA", "AA99 9AA", "A9A 9AA", "AA9A 9AA",
|
|
9
|
+
"SW1A 0AA", "SW1A 0PW", "SW1A 1AA", "SW1A 2HQ", "W1A 1AA", "W1A 1AB",
|
|
10
|
+
"N81 1ER", "EH99 1SP" ]
|
|
11
|
+
VALID_OUTCODES = VALID_SAMPLES.map{ |s| s.split(/\s/).first }
|
|
12
|
+
VALID_INCODES = VALID_SAMPLES.map{ |s| s.split(/\s/).last }
|
|
13
|
+
|
|
14
|
+
context "full samples with spaces" do
|
|
15
|
+
setup do
|
|
16
|
+
@samples = VALID_SAMPLES
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
should "all be valid" do
|
|
20
|
+
@samples.each do |sample|
|
|
21
|
+
assert UKPostcode.new(sample).valid?, "'#{sample}' should be valid"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
should "all be full" do
|
|
26
|
+
@samples.each do |sample|
|
|
27
|
+
assert UKPostcode.new(sample).full?, "'#{sample}' should be full"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
should "extract outcodes" do
|
|
32
|
+
@samples.zip(VALID_OUTCODES).each do |sample, outcode|
|
|
33
|
+
assert_equal outcode, UKPostcode.new(sample).outcode
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
should "extract incodes" do
|
|
38
|
+
@samples.zip(VALID_INCODES).each do |sample, incode|
|
|
39
|
+
assert_equal incode, UKPostcode.new(sample).incode
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context "full samples without spaces" do
|
|
45
|
+
setup do
|
|
46
|
+
@samples = VALID_SAMPLES.map{ |s| s.sub(/\s/, "") }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
should "all be valid" do
|
|
50
|
+
@samples.each do |sample|
|
|
51
|
+
assert UKPostcode.new(sample).valid?, "'#{sample}' should be valid"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
should "all be full" do
|
|
56
|
+
@samples.each do |sample|
|
|
57
|
+
assert UKPostcode.new(sample).full?, "'#{sample}' should be full"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
should "extract outcodes" do
|
|
62
|
+
@samples.zip(VALID_OUTCODES).each do |sample, outcode|
|
|
63
|
+
assert_equal outcode, UKPostcode.new(sample).outcode
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
should "extract incodes" do
|
|
68
|
+
@samples.zip(VALID_INCODES).each do |sample, incode|
|
|
69
|
+
assert_equal incode, UKPostcode.new(sample).incode
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context "outcode samples" do
|
|
75
|
+
setup do
|
|
76
|
+
@samples = VALID_OUTCODES
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
should "all be valid" do
|
|
80
|
+
@samples.each do |sample|
|
|
81
|
+
assert UKPostcode.new(sample).valid?, "'#{sample}' should be valid"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
should "not be full" do
|
|
86
|
+
@samples.each do |sample|
|
|
87
|
+
assert !UKPostcode.new(sample).full?, "'#{sample}' should not be full"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
should "keep outcode unchanged" do
|
|
92
|
+
@samples.each do |sample|
|
|
93
|
+
assert_equal sample, UKPostcode.new(sample).outcode
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
should "have nil incode" do
|
|
98
|
+
@samples.each do |sample|
|
|
99
|
+
assert_nil UKPostcode.new(sample).incode
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
context "when the postcode is supplied in lower case" do
|
|
105
|
+
setup do
|
|
106
|
+
@postcode = UKPostcode.new("w1a 1aa")
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
should "extract outcode in upper case" do
|
|
110
|
+
assert_equal "W1A", @postcode.outcode
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
should "extract incode in upper case" do
|
|
114
|
+
assert_equal "1AA", @postcode.incode
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
should "be valid" do
|
|
118
|
+
assert @postcode.valid?
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
{ "when the postcode is blank" => "",
|
|
123
|
+
"when the incode is truncated" => "W1A 1A",
|
|
124
|
+
"when the outcode is truncated" => "W",
|
|
125
|
+
"when the postcode is invalid" => "ABC DEFG"
|
|
126
|
+
}.each do |desc, sample|
|
|
127
|
+
context desc do
|
|
128
|
+
setup do
|
|
129
|
+
@postcode = UKPostcode.new(sample)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
should "not be valid" do
|
|
133
|
+
assert !@postcode.valid?
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
should "not be full" do
|
|
137
|
+
assert !@postcode.full?
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
should "return an empty string for to_str" do
|
|
141
|
+
assert_equal "", @postcode.to_str
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
should "return nil for outcode" do
|
|
145
|
+
assert_nil @postcode.outcode
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
should "return nil for incode" do
|
|
149
|
+
assert_nil @postcode.incode
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context "when used as a string" do
|
|
155
|
+
should "normalise spacing" do
|
|
156
|
+
assert_equal "W1A 1AA", UKPostcode.new("W1A1AA").to_str
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
should "convert case" do
|
|
160
|
+
assert_equal "W1A 1AA", UKPostcode.new("w1a 1aa").to_str
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
should "ignore a missing incode" do
|
|
164
|
+
assert_equal "W1A", UKPostcode.new("W1A").to_str
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
should "have same output for to_s and to_str" do
|
|
169
|
+
["W1A1AA", "w1a 1aa", "W1A"].each do |s|
|
|
170
|
+
postcode = UKPostcode.new(s)
|
|
171
|
+
assert_equal s.to_str, s.to_s
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: uk_postcode
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Paul Battley
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2010-01-06 00:00:00 +00:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: thoughtbot-shoulda
|
|
17
|
+
type: :development
|
|
18
|
+
version_requirement:
|
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
20
|
+
requirements:
|
|
21
|
+
- - ">="
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: "0"
|
|
24
|
+
version:
|
|
25
|
+
description:
|
|
26
|
+
email: pbattley@gmail.com
|
|
27
|
+
executables: []
|
|
28
|
+
|
|
29
|
+
extensions: []
|
|
30
|
+
|
|
31
|
+
extra_rdoc_files: []
|
|
32
|
+
|
|
33
|
+
files:
|
|
34
|
+
- Rakefile
|
|
35
|
+
- README.md
|
|
36
|
+
- test/test_uk_postcode.rb
|
|
37
|
+
- lib/uk_postcode.rb
|
|
38
|
+
has_rdoc: true
|
|
39
|
+
homepage:
|
|
40
|
+
licenses: []
|
|
41
|
+
|
|
42
|
+
post_install_message:
|
|
43
|
+
rdoc_options: []
|
|
44
|
+
|
|
45
|
+
require_paths:
|
|
46
|
+
- lib
|
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
48
|
+
requirements:
|
|
49
|
+
- - ">="
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: "0"
|
|
52
|
+
version:
|
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
54
|
+
requirements:
|
|
55
|
+
- - ">="
|
|
56
|
+
- !ruby/object:Gem::Version
|
|
57
|
+
version: "0"
|
|
58
|
+
version:
|
|
59
|
+
requirements: []
|
|
60
|
+
|
|
61
|
+
rubyforge_project:
|
|
62
|
+
rubygems_version: 1.3.5
|
|
63
|
+
signing_key:
|
|
64
|
+
specification_version: 3
|
|
65
|
+
summary: UK postcode parsing and validation
|
|
66
|
+
test_files: []
|
|
67
|
+
|