dc_address_parser 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +44 -0
- data/Rakefile +6 -0
- data/dc_address_parser.gemspec +28 -0
- data/lib/dc_address_parser.rb +10 -0
- data/lib/dc_address_parser/address.rb +195 -0
- data/lib/dc_address_parser/version.rb +3 -0
- data/script/bootstrap +3 -0
- data/script/cibuild +3 -0
- data/script/console +3 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 14263a461a3fe0f8d380d0e2694fdf0025332b8e
|
4
|
+
data.tar.gz: 01cca92f544be21c6315868c304b9af79dd6aed4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6b7158a7cb1d8e8e98698977a80bf7bcb8477c702bc0d708f51e7751e50ea711d1cabf1f1cc03b84ea3d8e577e86c9fcfd6aa34eb01ccc9d18dd9f9ed534fd3b
|
7
|
+
data.tar.gz: ce7e8cb159ceaa92d687a8db3e6f4c7216e1a7c42ae1831598d40a25a20f7a4329debf28e256e355a692d31e8cc87664aa7a80f6a923eecec7199b1d6ac117bb
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.4
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Ben Balter
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# DC Address Parser
|
2
|
+
|
3
|
+
*Parses and normalizes Washington, DC street addresses according to the DC Master Address Repository (MAR) standard.*
|
4
|
+
|
5
|
+
[![Build Status](https://travis-ci.org/benbalter/dc-address-parser.svg)](https://travis-ci.org/benbalter/dc-address-parser)
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
address = DcAddressParser.parse "123 main st n.w."
|
11
|
+
|
12
|
+
address.number
|
13
|
+
=> 123
|
14
|
+
|
15
|
+
address.street_name
|
16
|
+
=> "MAIN"
|
17
|
+
|
18
|
+
address.street_type
|
19
|
+
=> "STREET"
|
20
|
+
|
21
|
+
address.quadrant
|
22
|
+
=> "NW"
|
23
|
+
|
24
|
+
address.to_s
|
25
|
+
"123 MAIN STREET NW"
|
26
|
+
```
|
27
|
+
|
28
|
+
## Address standard
|
29
|
+
|
30
|
+
The Gem conforms to the [DC Master Address Repository (MAR) address standard](http://octo.dc.gov/sites/default/files/dc/sites/octo/publication/attachments/DCGIS-MarAddressStandards.pdf). You can learn more about the MAR in the [MAR FAQ](http://octo.dc.gov/sites/default/files/dc/sites/octo/publication/attachments/DCGIS-MarFAQ.pdf).
|
31
|
+
|
32
|
+
## Looking up addresses in the MAR
|
33
|
+
|
34
|
+
The Gem integrates with the [DC Address Lookup](https://github.com/benbalter/dc-address-lookup) gem. To look up an address in the MAR:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
address.lookup
|
38
|
+
=> #<DcAddressLookup::Location>
|
39
|
+
```
|
40
|
+
|
41
|
+
## Installing
|
42
|
+
|
43
|
+
1. Add `gem 'dc_address_parser'` to your project's Gemfile
|
44
|
+
2. `bundle install`
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dc_address_parser/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "dc_address_parser"
|
8
|
+
spec.version = DcAddressParser::VERSION
|
9
|
+
spec.authors = ["Ben Balter"]
|
10
|
+
spec.email = ["ben.balter@github.com"]
|
11
|
+
|
12
|
+
spec.summary = "Parses and normalizes Washington, DC street addresses according to the DC Master Address Repository (MAR) standard."
|
13
|
+
spec.homepage = "https://github.com/benbalter/dc-address-parser"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "activesupport", "~> 4.2"
|
22
|
+
spec.add_dependency "dc_address_lookup", "~> 0.2"
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
26
|
+
spec.add_development_dependency "pry", "~> 0.10"
|
27
|
+
spec.add_development_dependency "webmock", "~> 1.22"
|
28
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
module DcAddressParser
|
2
|
+
class Address
|
3
|
+
class InvalidAddress < StandardError; end
|
4
|
+
|
5
|
+
attr_reader :raw_address
|
6
|
+
|
7
|
+
CITY = "WASHINGTON, DC"
|
8
|
+
STREET_TYPES = {
|
9
|
+
"STREET" => "ST",
|
10
|
+
"AVENUE" => "AVE",
|
11
|
+
"BOULEVARD" => "BLVD",
|
12
|
+
"ROAD" => "RD",
|
13
|
+
"PLACE" => "PL",
|
14
|
+
"DRIVE" => "DR",
|
15
|
+
"CIRCLE" => "CIR",
|
16
|
+
"PALZA" => "PLZ",
|
17
|
+
"COURT" => "CT",
|
18
|
+
"ALLEY" => "AL",
|
19
|
+
"TERRACE" => "TER"
|
20
|
+
}
|
21
|
+
|
22
|
+
DIRECTIONS = {
|
23
|
+
"NORTH" => "N",
|
24
|
+
"SOUTH" => "S",
|
25
|
+
"EAST" => "E",
|
26
|
+
"WEST" => "W"
|
27
|
+
}
|
28
|
+
|
29
|
+
NUMBER_REGEX = /\A(\d+)[A-Z]*/
|
30
|
+
NUMBER_SUFFIX_REGEX = /(\d+\/\d+|rear)/i
|
31
|
+
STREET_NAME_REGEX = /([A-Z0-9' ]+)/
|
32
|
+
STREET_TYPE_REGEX = /\b(#{Regexp.union(STREET_TYPES.keys)})\b/
|
33
|
+
STREET_TYPE_ABV_REGEX = /\b(#{Regexp.union(STREET_TYPES.values)})\b/
|
34
|
+
QUADRANT_REGEX = /([NS][EW])/
|
35
|
+
|
36
|
+
REQUIRED_PARTS = [:number, :street_name, :street_type, :quadrant]
|
37
|
+
|
38
|
+
def initialize(raw_address)
|
39
|
+
@raw_address = @address = raw_address
|
40
|
+
normalize!
|
41
|
+
REQUIRED_PARTS.each do |part|
|
42
|
+
raise InvalidAddress, "#{part.to_s.sub("_", " ")} is missing" if send(part).nil?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def number
|
47
|
+
@number ||= match(NUMBER_REGEX).to_i
|
48
|
+
end
|
49
|
+
|
50
|
+
def number_suffix
|
51
|
+
@number_suffix ||= match(/#{number}\s#{NUMBER_SUFFIX_REGEX}/)
|
52
|
+
end
|
53
|
+
alias_method :suffix, :number_suffix
|
54
|
+
|
55
|
+
def street_name
|
56
|
+
@street_name ||= begin
|
57
|
+
street_name = match(
|
58
|
+
/#{number}(-?#{unit_number}|\s#{Regexp.escape number_suffix.to_s})?
|
59
|
+
\s#{STREET_NAME_REGEX}\s#{STREET_TYPE_REGEX}/x, 2)
|
60
|
+
|
61
|
+
if street_name =~ /\A[0-9]+\z/
|
62
|
+
street_name = ActiveSupport::Inflector.ordinalize(street_name).upcase
|
63
|
+
end
|
64
|
+
|
65
|
+
street_name
|
66
|
+
end
|
67
|
+
end
|
68
|
+
alias_method :street, :street_name
|
69
|
+
|
70
|
+
def street_type
|
71
|
+
@street_type ||= match STREET_TYPE_REGEX
|
72
|
+
end
|
73
|
+
|
74
|
+
def quadrant
|
75
|
+
@quadrant ||= match QUADRANT_REGEX
|
76
|
+
end
|
77
|
+
alias_method :quad, :quadrant
|
78
|
+
|
79
|
+
def unit_number
|
80
|
+
@unit_number ||= begin
|
81
|
+
unit_number = match(/\A(\d+)(-|–)?([A-Z])\b/) ||
|
82
|
+
match(/\s(UNIT\s|APT\s|#)([A-Z0-9]+)(\s|\z)/, 2) ||
|
83
|
+
match(/#{quadrant}\s([A-Z0-9]+)\z/)
|
84
|
+
if unit_number =~ /\A\d+\z/
|
85
|
+
unit_number.to_i
|
86
|
+
else
|
87
|
+
unit_number
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
alias_method :unit, :unit_number
|
92
|
+
|
93
|
+
def to_h
|
94
|
+
{
|
95
|
+
number: number,
|
96
|
+
number_suffix: number_suffix,
|
97
|
+
street_name: street_name,
|
98
|
+
street_type: street_type,
|
99
|
+
quadrant: quadrant,
|
100
|
+
unit_number: unit_number,
|
101
|
+
city: CITY
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def to_s(include_city=false)
|
106
|
+
parts = to_h
|
107
|
+
if include_city
|
108
|
+
parts[:quadrant] << ","
|
109
|
+
else
|
110
|
+
parts.delete(:city)
|
111
|
+
end
|
112
|
+
parts.values.compact.join(" ")
|
113
|
+
end
|
114
|
+
|
115
|
+
def lookup
|
116
|
+
DcAddressLookup.lookup to_s
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def normalize!
|
122
|
+
normalize_whitespace
|
123
|
+
normalize_case
|
124
|
+
normalize_ranges
|
125
|
+
normalize_quadrant
|
126
|
+
normalize_street_type
|
127
|
+
normalize_rear
|
128
|
+
normalize_space
|
129
|
+
normalize_mlk
|
130
|
+
normalize_directions
|
131
|
+
normalize_mt
|
132
|
+
split
|
133
|
+
end
|
134
|
+
|
135
|
+
def normalize_whitespace
|
136
|
+
@address = @address.strip.squeeze("\s").squeeze("'")
|
137
|
+
end
|
138
|
+
|
139
|
+
def normalize_case
|
140
|
+
@address = @address.upcase
|
141
|
+
end
|
142
|
+
|
143
|
+
def normalize_ranges
|
144
|
+
@address.gsub!(/\A(\d+)\s?(-|–|&)\s?\d+/, '\1')
|
145
|
+
@address.gsub!(/(\d+), \d+,? and \d+/i, '\1')
|
146
|
+
end
|
147
|
+
|
148
|
+
def normalize_quadrant
|
149
|
+
@address.gsub!(/([NS])\.([EW])\.?/, '\1\2')
|
150
|
+
@address.gsub!(/, ([NS][EW])/, ' \1')
|
151
|
+
end
|
152
|
+
|
153
|
+
def normalize_street_type
|
154
|
+
@address.gsub!(STREET_TYPE_ABV_REGEX, STREET_TYPES.invert)
|
155
|
+
end
|
156
|
+
|
157
|
+
def normalize_rear
|
158
|
+
regex = /\AREAR OF (\d+)/
|
159
|
+
return unless @address =~ regex
|
160
|
+
@address.gsub!(/\AREAR OF (\d+)/, '\1')
|
161
|
+
@address << " REAR"
|
162
|
+
end
|
163
|
+
|
164
|
+
def normalize_space
|
165
|
+
@address.gsub!(/\bSPACE\b/, "UNIT")
|
166
|
+
end
|
167
|
+
|
168
|
+
def normalize_mlk
|
169
|
+
@address.gsub!(/\bM\.?L\.? KING\b/, "MARTIN LUTHER KING")
|
170
|
+
@address.gsub!(/\bJR\./, "JR")
|
171
|
+
end
|
172
|
+
|
173
|
+
def normalize_directions
|
174
|
+
regex = /\b(#{Regexp.union DIRECTIONS.values})(?=\s+|\.)/
|
175
|
+
@address.gsub!(regex, DIRECTIONS.invert)
|
176
|
+
end
|
177
|
+
|
178
|
+
def normalize_mt
|
179
|
+
@address.gsub!(/\bMT\b/, "MOUNT")
|
180
|
+
end
|
181
|
+
|
182
|
+
def split
|
183
|
+
@address = @address.split(";").reject { |s| s.empty? }.first.to_s
|
184
|
+
@address = @address.split(/\bAND\b/).first.to_s.strip
|
185
|
+
@address = @address.split(/\b([NS][EW]),/)[0..1].join
|
186
|
+
end
|
187
|
+
|
188
|
+
def match(regex, number=nil)
|
189
|
+
matches = @address.match(regex)
|
190
|
+
return unless matches
|
191
|
+
return matches[number] if number
|
192
|
+
matches.to_a.last
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
data/script/bootstrap
ADDED
data/script/cibuild
ADDED
data/script/console
ADDED
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dc_address_parser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ben Balter
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dc_address_lookup
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.11'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.11'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.10'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.10'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webmock
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.22'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.22'
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- ben.balter@github.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- ".rspec"
|
120
|
+
- ".ruby-version"
|
121
|
+
- ".travis.yml"
|
122
|
+
- Gemfile
|
123
|
+
- LICENSE.txt
|
124
|
+
- README.md
|
125
|
+
- Rakefile
|
126
|
+
- dc_address_parser.gemspec
|
127
|
+
- lib/dc_address_parser.rb
|
128
|
+
- lib/dc_address_parser/address.rb
|
129
|
+
- lib/dc_address_parser/version.rb
|
130
|
+
- script/bootstrap
|
131
|
+
- script/cibuild
|
132
|
+
- script/console
|
133
|
+
homepage: https://github.com/benbalter/dc-address-parser
|
134
|
+
licenses:
|
135
|
+
- MIT
|
136
|
+
metadata: {}
|
137
|
+
post_install_message:
|
138
|
+
rdoc_options: []
|
139
|
+
require_paths:
|
140
|
+
- lib
|
141
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
requirements: []
|
152
|
+
rubyforge_project:
|
153
|
+
rubygems_version: 2.5.1
|
154
|
+
signing_key:
|
155
|
+
specification_version: 4
|
156
|
+
summary: Parses and normalizes Washington, DC street addresses according to the DC
|
157
|
+
Master Address Repository (MAR) standard.
|
158
|
+
test_files: []
|