us_street 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 007d55a2a54e1d6e42573edb3f5dfab5515ff1b0
4
+ data.tar.gz: fb7aae9671e5168511a4de1708f6f6bb0068e3fc
5
+ SHA512:
6
+ metadata.gz: a27b13fc431432e3fabb57a88e160f7340d53c00361cf60bb67c80d3a5d49e0ba8f2ff3cbf930f0a2f89b2d0b3657bbef5e5befa705585b941ed0efaa7366594
7
+ data.tar.gz: 1ec41605f2e513dfce2d05158b141bda74baef754051e13fba1baaf6498397df5a75afc938e6c31f1f70d0994761f90e9ab24d0e7c7cc6c41de71846a7a50ec1
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ *.gem
16
+
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in us_street.gemspec
4
+ gemspec
5
+
6
+ gem 'rspec'
7
+ gem 'pry'
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Opendoor Labs
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # UsStreet
2
+
3
+ Parses and normalizes the street part of an address for US streets into it's parts.
4
+
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'us_street'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install us_street
21
+
22
+ ## Usage
23
+
24
+ Can make sense of most streets
25
+
26
+ street = UsStreet.parse('123 north Fake street south 2034 #12')
27
+
28
+ # component accessors
29
+ street.street_number == '123'
30
+ street.dir_prefix == 'N'
31
+ street.street_name == 'Fake'
32
+ street.street_suffix == 'St'
33
+ street.dir_suffix == 'S'
34
+ street.road_number == '2034'
35
+ street.unit == '12'
36
+
37
+ street.street == 'N Fake St S 2034'
38
+ street.full_street == '123 N Fake St S 2034'
39
+ street.display == '123 N Fake St S 2034 #12'
40
+
41
+ It also works on simple streets
42
+
43
+ street = UsStreet.parse('12 st')
44
+ street.full_street = '12th St'
45
+
46
+ street = UsStreet.parse('123 north 12 st')
47
+ street.full_street == '123 N 12th St'
48
+
49
+ street = UsStreet.parse('123 something road')
50
+ street.full_street == '123 Something Rd'
51
+
52
+ ## Contributing
53
+
54
+ 1. Fork it ( https://github.com/[my-github-username]/us_street/fork )
55
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
56
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
57
+ 4. Push to the branch (`git push origin my-new-feature`)
58
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,550 @@
1
+ ---
2
+ alley: aly
3
+ allee: aly
4
+ aly: aly
5
+ ally: aly
6
+ anex: anx
7
+ anx: anx
8
+ annex: anx
9
+ annx: anx
10
+ arcade: arc
11
+ arc: arc
12
+ avenue: ave
13
+ av: ave
14
+ ave: ave
15
+ aven: ave
16
+ avenu: ave
17
+ avn: ave
18
+ avnue: ave
19
+ bayou: byu
20
+ bayoo: byu
21
+ byu: byu
22
+ beach: bch
23
+ bch: bch
24
+ bend: bnd
25
+ bnd: bnd
26
+ bluff: blf
27
+ blf: blf
28
+ bluf: blf
29
+ bluffs: blfs
30
+ blfs: blfs
31
+ bottom: btm
32
+ bot: btm
33
+ btm: btm
34
+ bottm: btm
35
+ boulevard: blvd
36
+ blvd: blvd
37
+ boul: blvd
38
+ boulv: blvd
39
+ branch: br
40
+ br: br
41
+ brnch: br
42
+ bridge: brg
43
+ brdge: brg
44
+ brg: brg
45
+ brook: brk
46
+ brk: brk
47
+ brooks: brks
48
+ brks: brks
49
+ burg: bg
50
+ bg: bg
51
+ burgs: bgs
52
+ bgs: bgs
53
+ bypass: byp
54
+ byp: byp
55
+ bypa: byp
56
+ bypas: byp
57
+ byps: byp
58
+ camp: cp
59
+ cp: cp
60
+ cmp: cp
61
+ canyon: cyn
62
+ canyn: cyn
63
+ cyn: cyn
64
+ cnyn: cyn
65
+ cape: cpe
66
+ cpe: cpe
67
+ causeway: cswy
68
+ cswy: cswy
69
+ causwa: cswy
70
+ center: ctr
71
+ cen: ctr
72
+ ctr: ctr
73
+ cent: ctr
74
+ centr: ctr
75
+ centre: ctr
76
+ cnter: ctr
77
+ cntr: ctr
78
+ centers: ctrs
79
+ ctrs: ctrs
80
+ circle: cir
81
+ cir: cir
82
+ circ: cir
83
+ circl: cir
84
+ crcl: cir
85
+ crcle: cir
86
+ circles: cirs
87
+ cirs: cirs
88
+ cliff: clf
89
+ clf: clf
90
+ cliffs: clfs
91
+ clfs: clfs
92
+ club: clb
93
+ clb: clb
94
+ common: cmn
95
+ cmn: cmn
96
+ commons: cmns
97
+ cmns: cmns
98
+ corner: cor
99
+ cor: cor
100
+ corners: cors
101
+ cors: cors
102
+ course: crse
103
+ crse: crse
104
+ court: ct
105
+ ct: ct
106
+ courts: cts
107
+ cts: cts
108
+ cove: cv
109
+ cv: cv
110
+ coves: cvs
111
+ cvs: cvs
112
+ creek: crk
113
+ crk: crk
114
+ crescent: cres
115
+ cres: cres
116
+ crsent: cres
117
+ crsnt: cres
118
+ crest: crst
119
+ crst: crst
120
+ crossing: xing
121
+ xing: xing
122
+ crssng: xing
123
+ crossroad: xrd
124
+ xrd: xrd
125
+ crossroads: xrds
126
+ xrds: xrds
127
+ curve: curv
128
+ curv: curv
129
+ dale: dl
130
+ dl: dl
131
+ dam: dm
132
+ dm: dm
133
+ divide: dv
134
+ div: dv
135
+ dv: dv
136
+ dvd: dv
137
+ drive: dr
138
+ dr: dr
139
+ driv: dr
140
+ drv: dr
141
+ drives: drs
142
+ drs: drs
143
+ estate: est
144
+ est: est
145
+ estates: ests
146
+ ests: ests
147
+ expressway: expy
148
+ exp: expy
149
+ expy: expy
150
+ expr: expy
151
+ express: expy
152
+ expw: expy
153
+ extension: ext
154
+ ext: ext
155
+ extn: ext
156
+ extnsn: ext
157
+ extensions: exts
158
+ exts: exts
159
+ fall: fall
160
+ falls: fls
161
+ fls: fls
162
+ ferry: fry
163
+ fry: fry
164
+ frry: fry
165
+ field: fld
166
+ fld: fld
167
+ fields: flds
168
+ flds: flds
169
+ flat: flt
170
+ flt: flt
171
+ flats: flts
172
+ flts: flts
173
+ ford: frd
174
+ frd: frd
175
+ fords: frds
176
+ frds: frds
177
+ forest: frst
178
+ frst: frst
179
+ forests: frst
180
+ forge: frg
181
+ forg: frg
182
+ frg: frg
183
+ forges: frgs
184
+ frgs: frgs
185
+ fork: frk
186
+ frk: frk
187
+ forks: frks
188
+ frks: frks
189
+ fort: ft
190
+ ft: ft
191
+ frt: ft
192
+ freeway: fwy
193
+ fwy: fwy
194
+ freewy: fwy
195
+ frway: fwy
196
+ frwy: fwy
197
+ garden: gdn
198
+ gdn: gdn
199
+ gardn: gdn
200
+ grden: gdn
201
+ grdn: gdn
202
+ gardens: gdns
203
+ gdns: gdns
204
+ grdns: gdns
205
+ gateway: gtwy
206
+ gtwy: gtwy
207
+ gatewy: gtwy
208
+ gatway: gtwy
209
+ gtway: gtwy
210
+ glen: gln
211
+ gln: gln
212
+ glens: glns
213
+ glns: glns
214
+ green: grn
215
+ grn: grn
216
+ greens: grns
217
+ grns: grns
218
+ grove: grv
219
+ grov: grv
220
+ grv: grv
221
+ groves: grvs
222
+ grvs: grvs
223
+ harbor: hbr
224
+ harb: hbr
225
+ hbr: hbr
226
+ harbr: hbr
227
+ hrbor: hbr
228
+ harbors: hbrs
229
+ hbrs: hbrs
230
+ haven: hvn
231
+ hvn: hvn
232
+ heights: hts
233
+ ht: hts
234
+ hts: hts
235
+ highway: hwy
236
+ hwy: hwy
237
+ highwy: hwy
238
+ hiway: hwy
239
+ hiwy: hwy
240
+ hway: hwy
241
+ hill: hl
242
+ hl: hl
243
+ hills: hls
244
+ hls: hls
245
+ hollow: holw
246
+ hllw: holw
247
+ holw: holw
248
+ hollows: holw
249
+ holws: holw
250
+ inlet: inlt
251
+ inlt: inlt
252
+ island: is
253
+ is: is
254
+ islnd: is
255
+ islands: iss
256
+ iss: iss
257
+ islnds: iss
258
+ isle: isle
259
+ isles: isle
260
+ junction: jct
261
+ jct: jct
262
+ jction: jct
263
+ jctn: jct
264
+ junctn: jct
265
+ juncton: jct
266
+ junctions: jcts
267
+ jctns: jcts
268
+ jcts: jcts
269
+ key: ky
270
+ ky: ky
271
+ keys: kys
272
+ kys: kys
273
+ knoll: knl
274
+ knl: knl
275
+ knol: knl
276
+ knolls: knls
277
+ knls: knls
278
+ lake: lk
279
+ lk: lk
280
+ lakes: lks
281
+ lks: lks
282
+ land: land
283
+ landing: lndg
284
+ lndg: lndg
285
+ lndng: lndg
286
+ lane: ln
287
+ ln: ln
288
+ light: lgt
289
+ lgt: lgt
290
+ lights: lgts
291
+ lgts: lgts
292
+ loaf: lf
293
+ lf: lf
294
+ lock: lck
295
+ lck: lck
296
+ locks: lcks
297
+ lcks: lcks
298
+ lodge: ldg
299
+ ldg: ldg
300
+ ldge: ldg
301
+ lodg: ldg
302
+ loop: loop
303
+ loops: loop
304
+ mall: mall
305
+ manor: mnr
306
+ mnr: mnr
307
+ manors: mnrs
308
+ mnrs: mnrs
309
+ meadow: mdw
310
+ mdw: mdws
311
+ meadows: mdws
312
+ mdws: mdws
313
+ medows: mdws
314
+ mews: mews
315
+ mill: ml
316
+ ml: ml
317
+ mills: mls
318
+ mls: mls
319
+ mission: msn
320
+ missn: msn
321
+ msn: msn
322
+ mssn: msn
323
+ motorway: mtwy
324
+ mtwy: mtwy
325
+ mount: mt
326
+ mnt: mt
327
+ mt: mt
328
+ mountain: mtn
329
+ mntain: mtn
330
+ mtn: mtn
331
+ mntn: mtn
332
+ mountin: mtn
333
+ mtin: mtn
334
+ mountains: mtns
335
+ mntns: mtns
336
+ mtns: mtns
337
+ neck: nck
338
+ nck: nck
339
+ orchard: orch
340
+ orch: orch
341
+ orchrd: orch
342
+ oval: oval
343
+ ovl: oval
344
+ overpass: opas
345
+ opas: opas
346
+ park: park
347
+ prk: park
348
+ parks: park
349
+ parkway: pkwy
350
+ pkwy: pkwy
351
+ parkwy: pkwy
352
+ pkway: pkwy
353
+ pky: pkwy
354
+ parkways: pkwy
355
+ pkwys: pkwy
356
+ pass: pass
357
+ passage: psge
358
+ psge: psge
359
+ path: path
360
+ paths: path
361
+ pike: pike
362
+ pikes: pike
363
+ pine: pne
364
+ pne: pne
365
+ pines: pnes
366
+ pnes: pnes
367
+ place: pl
368
+ pl: pl
369
+ plain: pln
370
+ pln: pln
371
+ plains: plns
372
+ plns: plns
373
+ plaza: plz
374
+ plz: plz
375
+ plza: plz
376
+ point: pt
377
+ pt: pt
378
+ points: pts
379
+ pts: pts
380
+ port: prt
381
+ prt: prt
382
+ ports: prts
383
+ prts: prts
384
+ prairie: pr
385
+ pr: pr
386
+ prr: pr
387
+ radial: radl
388
+ rad: radl
389
+ radl: radl
390
+ radiel: radl
391
+ ramp: ramp
392
+ ranch: rnch
393
+ rnch: rnch
394
+ ranches: rnch
395
+ rnchs: rnch
396
+ rapid: rpd
397
+ rpd: rpd
398
+ rapids: rpds
399
+ rpds: rpds
400
+ rest: rst
401
+ rst: rst
402
+ ridge: rdg
403
+ rdg: rdg
404
+ rdge: rdg
405
+ ridges: rdgs
406
+ rdgs: rdgs
407
+ river: riv
408
+ riv: riv
409
+ rvr: riv
410
+ rivr: riv
411
+ road: rd
412
+ rd: rd
413
+ roads: rds
414
+ rds: rds
415
+ route: rte
416
+ rte: rte
417
+ row: row
418
+ rue: rue
419
+ run: run
420
+ shoal: shl
421
+ shl: shl
422
+ shoals: shls
423
+ shls: shls
424
+ shore: shr
425
+ shoar: shr
426
+ shr: shr
427
+ shores: shrs
428
+ shoars: shrs
429
+ shrs: shrs
430
+ skyway: skwy
431
+ skwy: skwy
432
+ spring: spg
433
+ spg: spg
434
+ spng: spg
435
+ sprng: spg
436
+ springs: spgs
437
+ spgs: spgs
438
+ spngs: spgs
439
+ sprngs: spgs
440
+ spur: spur
441
+ spurs: spur
442
+ square: sq
443
+ sq: sq
444
+ sqr: sq
445
+ sqre: sq
446
+ squ: sq
447
+ squares: sqs
448
+ sqrs: sqs
449
+ sqs: sqs
450
+ station: sta
451
+ sta: sta
452
+ statn: sta
453
+ stn: sta
454
+ stravenue: stra
455
+ stra: stra
456
+ strav: stra
457
+ straven: stra
458
+ stravn: stra
459
+ strvn: stra
460
+ strvnue: stra
461
+ stream: strm
462
+ strm: strm
463
+ streme: strm
464
+ street: st
465
+ st: st
466
+ strt: st
467
+ str: st
468
+ streets: sts
469
+ sts: sts
470
+ summit: smt
471
+ smt: smt
472
+ sumit: smt
473
+ sumitt: smt
474
+ terrace: ter
475
+ ter: ter
476
+ terr: ter
477
+ throughway: trwy
478
+ trwy: trwy
479
+ trace: trce
480
+ trce: trce
481
+ traces: trce
482
+ track: trak
483
+ trak: trak
484
+ tracks: trak
485
+ trk: trak
486
+ trks: trak
487
+ trafficway: trfy
488
+ trfy: trfy
489
+ trail: trl
490
+ trl: trl
491
+ trails: trl
492
+ trls: trl
493
+ trailer: trlr
494
+ trlr: trlr
495
+ trlrs: trlr
496
+ tunnel: tunl
497
+ tunel: tunl
498
+ tunl: tunl
499
+ tunls: tunl
500
+ tunnels: tunl
501
+ tunnl: tunl
502
+ turnpike: tpke
503
+ trnpk: tpke
504
+ tpke: tpke
505
+ turnpk: tpke
506
+ underpass: upas
507
+ upas: upas
508
+ union: un
509
+ un: un
510
+ unions: uns
511
+ uns: uns
512
+ valley: vly
513
+ vly: vly
514
+ vally: vly
515
+ vlly: vly
516
+ valleys: vlys
517
+ vlys: vlys
518
+ viaduct: via
519
+ vdct: via
520
+ via: via
521
+ viadct: via
522
+ view: vw
523
+ vw: vw
524
+ views: vws
525
+ vws: vws
526
+ village: vlg
527
+ vill: vlg
528
+ vlg: vlg
529
+ villag: vlg
530
+ villg: vlg
531
+ villiage: vlg
532
+ villages: vlgs
533
+ vlgs: vlgs
534
+ ville: vl
535
+ vl: vl
536
+ vista: vis
537
+ vis: vis
538
+ vist: vis
539
+ vst: vis
540
+ vsta: vis
541
+ walk: walk
542
+ walks: walk
543
+ wall: wall
544
+ way: way
545
+ wy: way
546
+ ways: ways
547
+ well: wl
548
+ wl: wl
549
+ wells: wls
550
+ wls: wls
@@ -0,0 +1,3 @@
1
+ class UsStreet
2
+ VERSION = "0.1.0"
3
+ end
data/lib/us_street.rb ADDED
@@ -0,0 +1,172 @@
1
+ require "us_street/version"
2
+ require 'yaml'
3
+ require 'active_support/core_ext/object/blank'
4
+ require 'active_support/core_ext/hash/indifferent_access'
5
+ require 'active_support/core_ext/object/try'
6
+ require 'active_support/inflector/inflections'
7
+ require 'active_support/core_ext/integer/inflections'
8
+
9
+ class UsStreet
10
+ COMPONENTS = [:unit, :street_number, :dir_prefix, :street_name, :street_suffix, :dir_suffix, :road_number].freeze
11
+
12
+ f = File.expand_path('data/street_suffix_mapping.yml', __dir__)
13
+ ROAD_SUFFIXES = YAML.load(File.read(f))
14
+
15
+ DIRECTIONAL_MAPPINGS = {
16
+ "n" => "n",
17
+ "e" => "e",
18
+ "s" => "s",
19
+ "w" => "w",
20
+ "north" => "n",
21
+ "east" => "e",
22
+ "south" => "s",
23
+ "west" => "w",
24
+ "nth" => "n",
25
+ "sth" => "s",
26
+ "ne" => "ne",
27
+ "nw" => "nw",
28
+ "se" => "se",
29
+ "sw" => "sw",
30
+ "northeast" => "ne",
31
+ "northwest" => "nw",
32
+ "southeast" => "se",
33
+ "southwest" => "sw",
34
+ }
35
+
36
+ def self.components; COMPONENTS; end
37
+
38
+ def self.clean(str)
39
+ str.to_s.gsub(/([\.,:;]|\(.*?\))/, '').gsub(/#\d+$/, '').gsub(/\s+/, ' ').strip.downcase.presence
40
+ end
41
+
42
+ def self.clean_hash(hash)
43
+ hash.each_with_object({}.with_indifferent_access) { |(k,v),hsh| hsh[k] = clean(v) }
44
+ end
45
+
46
+ # Define methods for each of the components
47
+ components.each do |f|
48
+ define_method(f) { @components[f] }
49
+ end
50
+
51
+ attr_reader :components
52
+
53
+ # @param {String} street_number - The street number
54
+ # @param {String} street_name - The name of the street including all the 'ixes
55
+ # @param {Hash} components - The components of the street
56
+ def initialize(components = {})
57
+ @components = components
58
+ end
59
+
60
+ def street
61
+ @street ||= UsStreet.trim(dir_prefix, street_name, street_suffix, dir_suffix, road_number)
62
+ end
63
+
64
+ def full_street
65
+ @full_street ||= UsStreet.trim(street_number, street)
66
+ end
67
+
68
+ def display
69
+ @display ||= unit.present? ? UsStreet.trim(full_street, "##{unit}") : full_street
70
+ end
71
+
72
+ def attributes
73
+ @attributes ||= @components.merge(street: street, full_street: full_street, display: display)
74
+ end
75
+
76
+ def self.parse(full_street, overrides = {})
77
+ original_full_street = full_street.to_s
78
+ full_street = clean(full_street.to_s).to_s # the cleaner removes unit numbers :(
79
+ overrides = clean_hash(overrides)
80
+
81
+ parts = full_street.split(' ')
82
+ sidx, eidx = 0, parts.length - 1
83
+ unit_number = dir_suffix = dir_prefix = street_suffix = street_number = road_number = nil
84
+
85
+ # start at the end and chomp
86
+
87
+ # We could have a unit number last. Format '#\d+' but it's removed by the cleaners so match the original
88
+ if match = original_full_street.match(/#(\d+)$/)
89
+ unit_number = match[1]
90
+ end
91
+
92
+ # we may be on a numbered road. Like a country road.
93
+ if parts[eidx] =~ /^\d+$/
94
+ road_number = parts[eidx]
95
+ eidx -= 1
96
+ end
97
+
98
+ # We may have a directional suffix, and or a street suffix
99
+ eidx -= 1 if dir_suffix = direction_mapping(parts[eidx])
100
+ eidx -= 1 if street_suffix = road_mapping(parts[eidx])
101
+
102
+ # if our current spread is 0 then someone may have put in 12 st for 12th Street. We want to end it here if that's true.
103
+ if eidx - sidx > 0
104
+ # lets look at the start of the string
105
+
106
+ # is there a street number?
107
+ if parts[sidx] =~ /^\d+$/
108
+ street_number = parts[sidx]
109
+ sidx += 1
110
+ end
111
+
112
+ # is there a directional prefix?
113
+ sidx += 1 if dir_prefix = direction_mapping(parts[sidx])
114
+ end
115
+
116
+ # fix weirdo street names and make them consistent
117
+ parts[sidx] = "St" if parts[sidx] =~ /^((st\.?)|(saint))$/i # catch "Saint John Street"
118
+ parts[sidx] = "Dr" if parts[sidx] =~ /^((dr\.?)|(doctor))$/i # catch "Dr. Oz Road"
119
+
120
+ # Time to build up the output, prefer what was passed in
121
+ # Note: We needed to decompose the street because the street may have had the components put into it
122
+ # by some unsavoury operators :'(
123
+ out = {
124
+ unit: overrides[:unit].presence || unit_number,
125
+ dir_prefix: direction_mapping(overrides[:dir_prefix]).presence || dir_prefix,
126
+ street_name: overrides[:street_name].presence || parts[sidx..eidx].join(' '),
127
+ street_suffix: road_mapping(overrides[:street_suffix]).presence || street_suffix,
128
+ dir_suffix: direction_mapping(overrides[:dir_suffix]).presence || dir_suffix,
129
+ street_number: overrides[:street_number].presence || street_number,
130
+ road_number: overrides[:road_number].presence || road_number
131
+ }
132
+
133
+ # we may have country or co for a country road.
134
+ out[:street_name] = 'co' if out[:street_name] == 'country'
135
+
136
+ # perform one last mapping to be sure that we've got the correct 'ixes.
137
+ out[:dir_prefix] = out[:dir_prefix].try(:upcase)
138
+ out[:dir_suffix] = out[:dir_suffix].try(:upcase)
139
+ out[:street_suffix] = road_mapping(out[:street_suffix]).try(:titleize)
140
+ out[:street_name] = out[:street_name].try(:titleize)
141
+
142
+ out[:street_name] = out[:street_name].to_i.ordinalize if out[:street_name].present? && out[:street_name] =~ /^\d+$/
143
+
144
+ new out
145
+ end
146
+
147
+ def self.from_attrs(street_number, dir_prefix, street_name, street_suffix, dir_suffix)
148
+ return parse(
149
+ street_name,
150
+ street_number: street_number,
151
+ dir_prefix: dir_prefix,
152
+ street_suffix: street_suffix,
153
+ dir_suffix: dir_suffix
154
+ )
155
+ end
156
+
157
+ def self.direction_mapping(direction)
158
+ DIRECTIONAL_MAPPINGS[direction.to_s.downcase] && DIRECTIONAL_MAPPINGS[direction.to_s.downcase].upcase
159
+ end
160
+
161
+ def self.road_mapping(suffix)
162
+ ROAD_SUFFIXES[suffix.to_s.downcase] && ROAD_SUFFIXES[suffix.to_s.downcase].upcase
163
+ end
164
+
165
+ def self.trim(*address_components)
166
+ address_components.compact.join(' ').gsub(/\s+/, ' ').strip
167
+ end
168
+
169
+ def ==(other)
170
+ other.respond_to?(:full_street) && self.full_street == other.full_street
171
+ end
172
+ end
@@ -0,0 +1,8 @@
1
+ $:.unshift File.expand_path('../lib', __dir__)
2
+
3
+ require 'us_street'
4
+ require 'pry'
5
+
6
+ RSpec.configure do |config|
7
+ config.order = "random"
8
+ end
@@ -0,0 +1,208 @@
1
+ require 'spec_helper'
2
+
3
+ describe UsStreet do
4
+ describe ".from_attrs" do
5
+ it "builds a normalized street address" do
6
+ us_street = UsStreet.from_attrs(11421, "W", "LAURELWOOD", "Lane", nil)
7
+ expect(us_street.full_street).to eq("11421 W Laurelwood Ln")
8
+ end
9
+
10
+ it "removes unknown directions" do
11
+ us_street = UsStreet.from_attrs(11421, "WFS", "LAURELWOOD", "Lane", nil)
12
+ expect(us_street.full_street).to eq("11421 Laurelwood Ln")
13
+ end
14
+
15
+ it "simplifies known directions" do
16
+ us_street = UsStreet.from_attrs(11421, "NorthWesT", "LAURELWOOD", "Lane", "SE")
17
+ expect(us_street.full_street).to eq("11421 NW Laurelwood Ln SE")
18
+ end
19
+
20
+ it "checks for Saint & Doctor such-n'-such streets" do
21
+ us_street = UsStreet.from_attrs(11421, nil, "ST. JOHN", "Road", nil)
22
+ expect(us_street.full_street).to eq("11421 St John Rd")
23
+ us_street = UsStreet.from_attrs(11421, nil, "saInT John", "Road", nil)
24
+ expect(us_street.full_street).to eq("11421 St John Rd")
25
+
26
+ us_street = UsStreet.from_attrs(11421, nil, "DR JOHN", "Road", nil)
27
+ expect(us_street.full_street).to eq("11421 Dr John Rd")
28
+ us_street = UsStreet.from_attrs(11421, nil, "Doctor John", "Road", nil)
29
+ expect(us_street.full_street).to eq("11421 Dr John Rd")
30
+ end
31
+
32
+ it "removes stuff in parens" do
33
+ us_street = UsStreet.from_attrs(11421, "WFS", "LAURELWOOD (NOT HERE)", "Lane", nil)
34
+ expect(us_street.full_street).to eq("11421 Laurelwood Ln")
35
+ end
36
+
37
+ it "strips off unrequired characters" do
38
+ us_street = UsStreet.from_attrs(123, nil, "N. main, -southy", nil, nil)
39
+ expect(us_street.full_street).to eq("123 N Main Southy")
40
+ end
41
+
42
+ it "strips off spaces" do
43
+ us_street = UsStreet.from_attrs(" 123", nil, "N. main, -southy ", nil, nil)
44
+ expect(us_street.full_street).to eq("123 N Main Southy")
45
+ end
46
+
47
+ context 'with weird data' do
48
+ it 'checks for double entry of directional prefix' do
49
+ us_street = UsStreet.from_attrs(" 123", 'North', "N 12th St", nil, nil)
50
+ expect(us_street.full_street).to eq('123 N 12th St')
51
+ end
52
+
53
+ it 'checks for double entry of street suffix' do
54
+ us_street = UsStreet.from_attrs(" 123", nil, "N 12th St", 'Street', nil)
55
+ expect(us_street.full_street).to eq('123 N 12th St')
56
+ end
57
+
58
+ it 'checks for double entry of directional suffix' do
59
+ us_street = UsStreet.from_attrs(" 123", nil, "12th Street West", 'st', 'W')
60
+ expect(us_street.full_street).to eq('123 12th St W')
61
+ end
62
+
63
+ it 'handles all the suffixen and prefixen' do
64
+ us_street = UsStreet.from_attrs(" 123", 'S', "South 12th St East", 'Street', 'E')
65
+ expect(us_street.full_street).to eq('123 S 12th St E')
66
+ end
67
+
68
+ it 'reads the directional prefix from the street when not passed in' do
69
+ us_street = UsStreet.from_attrs(" 123", nil, 'southwest 12th St', nil, nil)
70
+ expect(us_street.full_street).to eq('123 SW 12th St')
71
+ end
72
+
73
+ it 'reads the street suffix from the street when not passed in' do
74
+ us_street = UsStreet.from_attrs(" 123", nil, "12th Street", nil, nil)
75
+ expect(us_street.full_street).to eq('123 12th St')
76
+ end
77
+
78
+ it 'reads the directional suffix from the street when not passed in' do
79
+ us_street = UsStreet.from_attrs(" 123", nil, "12th North", 'Street', nil)
80
+ expect(us_street.full_street).to eq('123 12th St N')
81
+ end
82
+
83
+ it 'prefers what is passed in' do
84
+ us_street = UsStreet.from_attrs(" 123", 'S', "North 12th St WEST", 'Street', 'E')
85
+ expect(us_street.full_street).to eq('123 S 12th St E')
86
+ end
87
+ end
88
+ end
89
+
90
+ describe '.parse' do
91
+ it "builds a normalized street address" do
92
+ us_street = UsStreet.parse("11421 W LAURELWOOD Lane")
93
+ expect(us_street.full_street).to eq("11421 W Laurelwood Ln")
94
+ end
95
+
96
+ it "removes unknown directions" do
97
+ us_street = UsStreet.parse("11421 LAURELWOOD Lane", dir_prefix: 'WFS')
98
+ expect(us_street.full_street).to eq("11421 Laurelwood Ln")
99
+ end
100
+
101
+ it "simplifies known directions" do
102
+ us_street = UsStreet.parse("11421 NorthWesT LAURELWOOD Lane SE")
103
+ expect(us_street.full_street).to eq("11421 NW Laurelwood Ln SE")
104
+ end
105
+
106
+ it "checks for Saint & Doctor such-n'-such streets" do
107
+ us_street = UsStreet.parse("11421 ST. JOHN Road")
108
+ expect(us_street.full_street).to eq("11421 St John Rd")
109
+ us_street = UsStreet.parse("11421 saInT John Road")
110
+ expect(us_street.full_street).to eq("11421 St John Rd")
111
+
112
+ us_street = UsStreet.parse("11421 DR JOHN Road")
113
+ expect(us_street.full_street).to eq("11421 Dr John Rd")
114
+ us_street = UsStreet.parse("11421 Doctor John Road")
115
+ expect(us_street.full_street).to eq("11421 Dr John Rd")
116
+ end
117
+
118
+ it "removes stuff in parens" do
119
+ us_street = UsStreet.parse("11421 LAURELWOOD (NOT HERE) Lane")
120
+ expect(us_street.full_street).to eq("11421 Laurelwood Ln")
121
+ end
122
+
123
+ it "strips off unrequired characters" do
124
+ us_street = UsStreet.parse("123 N. main, -southy")
125
+ expect(us_street.full_street).to eq("123 N Main Southy")
126
+ end
127
+
128
+ it "strips off spaces" do
129
+ us_street = UsStreet.parse(" 123 N main southy ")
130
+ expect(us_street.full_street).to eq("123 N Main Southy")
131
+ end
132
+
133
+ it 'prefers an explicit dir_prefix' do
134
+ us_street = UsStreet.parse("123 S main southy", dir_prefix: "n")
135
+ expect(us_street.dir_prefix).to eq('N')
136
+ expect(us_street.full_street).to eq("123 N Main Southy")
137
+ end
138
+
139
+ it 'prefers an explicit dir_suffix' do
140
+ us_street = UsStreet.parse("123 main southy W", dir_suffix: "n")
141
+ expect(us_street.dir_suffix).to eq('N')
142
+ expect(us_street.full_street).to eq("123 Main Southy N")
143
+ end
144
+
145
+ it 'prefers an explicit street_suffix' do
146
+ us_street = UsStreet.parse("123 main southy road", street_suffix: "st")
147
+ expect(us_street.street_suffix).to eq('St')
148
+ expect(us_street.full_street).to eq("123 Main Southy St")
149
+ end
150
+
151
+ it 'handles unit numbers' do
152
+ us_street = UsStreet.parse('123 123rd st #15')
153
+ expect(us_street.unit).to eq('15')
154
+ expect(us_street.full_street).to eq('123 123rd St')
155
+ expect(us_street.display).to eq('123 123rd St #15')
156
+ end
157
+
158
+ it 'handles 123rd st without ordinals or street number' do
159
+ us_street = UsStreet.parse('123 st')
160
+ expect(us_street.street_number).to eq(nil)
161
+ expect(us_street.street_name).to eq('123rd')
162
+ expect(us_street.full_street).to eq('123rd St')
163
+ end
164
+
165
+ it 'handles non ordinalized street names' do
166
+ us_street = UsStreet.parse('13 1 st #14')
167
+ expect(us_street.street_number).to eq('13')
168
+ expect(us_street.unit).to eq('14')
169
+ expect(us_street.street_name).to eq('1st')
170
+ expect(us_street.full_street).to eq('13 1st St')
171
+ expect(us_street.display).to eq('13 1st St #14')
172
+ end
173
+
174
+ it 'handles overrides with string keys' do
175
+ us_street = UsStreet.parse('123 Fake st', "unit" => 12)
176
+ expect(us_street.unit).to eq('12')
177
+ end
178
+
179
+ it 'handles country roads' do
180
+ street1 = UsStreet.parse('1455 Indian Rte 9500')
181
+ street2 = UsStreet.parse('1455 Country Road 2085')
182
+
183
+ expect(street1.full_street).to eq('1455 Indian Rte 9500')
184
+ expect(street1.street_number).to eq('1455')
185
+ expect(street1.street_name).to eq('Indian')
186
+ expect(street1.road_number).to eq('9500')
187
+ expect(street1.street_suffix).to eq('Rte')
188
+ expect(street1.unit).to be_nil
189
+
190
+ expect(street2.full_street).to eq('1455 Co Rd 2085')
191
+ expect(street2.street_number).to eq('1455')
192
+ expect(street2.street_name).to eq('Co')
193
+ expect(street2.road_number).to eq('2085')
194
+ expect(street2.street_suffix).to eq('Rd')
195
+ expect(street2.unit).to be_nil
196
+ end
197
+
198
+ it 'handles country roads with units' do
199
+ street = UsStreet.parse('1455 Country Road 2085 #12')
200
+ expect(street.full_street).to eq('1455 Co Rd 2085')
201
+ expect(street.street_number).to eq('1455')
202
+ expect(street.street_name).to eq('Co')
203
+ expect(street.road_number).to eq('2085')
204
+ expect(street.street_suffix).to eq('Rd')
205
+ expect(street.unit).to eq('12')
206
+ end
207
+ end
208
+ end
data/us_street.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'us_street/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "us_street"
8
+ spec.version = UsStreet::VERSION
9
+ spec.authors = ["Daniel Neighman"]
10
+ spec.email = ["has.sox@gmail.com"]
11
+ spec.summary = %q{Normalizes Us Streets}
12
+ spec.description = %q{Normalizes Us Streets}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'activesupport', '>=3.0'
22
+ spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: us_street
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Neighman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-12 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: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ description: Normalizes Us Streets
56
+ email:
57
+ - has.sox@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - LICENSE.txt
65
+ - README.md
66
+ - Rakefile
67
+ - lib/data/street_suffix_mapping.yml
68
+ - lib/us_street.rb
69
+ - lib/us_street/version.rb
70
+ - spec/spec_helper.rb
71
+ - spec/us_street_spec.rb
72
+ - us_street.gemspec
73
+ homepage: ''
74
+ licenses:
75
+ - MIT
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.2.2
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Normalizes Us Streets
97
+ test_files:
98
+ - spec/spec_helper.rb
99
+ - spec/us_street_spec.rb
100
+ has_rdoc: