lite-address 1.0.0 → 1.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 +4 -4
- data/.rubocop.yml +7 -2
- data/CHANGELOG.md +10 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +39 -55
- data/README.md +19 -15
- data/Rakefile +2 -2
- data/bin/console +3 -3
- data/lib/lite/address/format.rb +21 -40
- data/lib/lite/address/list.rb +29 -29
- data/lib/lite/address/parser.rb +38 -38
- data/lib/lite/address/regexp.rb +3 -3
- data/lib/lite/address/types/part.yml +17 -0
- data/lib/lite/address/ukey.rb +6 -8
- data/lib/lite/address/version.rb +1 -1
- data/lib/lite/address.rb +6 -6
- data/lite-address.gemspec +23 -30
- metadata +10 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 36e2c1997170c93506425dd544c0062935dcd259907358f65369939d2eaa6873
|
|
4
|
+
data.tar.gz: e49a679ac35e9112ace7cefcf692801764b75dfecc7c0fbe36d144906b4c1b2e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6325e5bbb27050fbb0d187c4a82f0198972c1cf570fd323bb08eb786bde058724c9dc678bd078e060c62b6a046b5474b9a172cc7793026bf83e6f7628b66b907
|
|
7
|
+
data.tar.gz: 8f345971caa3e404ab079b970f07e2e4bab655c2c64eba1abf93af3b69f593857c1853dc1fb791a290268709a1eb8ea74d936cc21dc9b423ec5cd0d1f66fd891
|
data/.rubocop.yml
CHANGED
|
@@ -3,7 +3,6 @@ require:
|
|
|
3
3
|
- rubocop-rake
|
|
4
4
|
- rubocop-rspec
|
|
5
5
|
AllCops:
|
|
6
|
-
TargetRubyVersion: 3.0
|
|
7
6
|
NewCops: enable
|
|
8
7
|
DisplayCopNames: true
|
|
9
8
|
DisplayStyleGuide: true
|
|
@@ -19,13 +18,15 @@ Layout/EmptyLinesAroundClassBody:
|
|
|
19
18
|
Layout/EmptyLinesAroundModuleBody:
|
|
20
19
|
EnforcedStyle: empty_lines_except_namespace
|
|
21
20
|
Layout/LineLength:
|
|
22
|
-
|
|
21
|
+
Enabled: false
|
|
23
22
|
Layout/SpaceAroundMethodCallOperator:
|
|
24
23
|
Enabled: true
|
|
25
24
|
Lint/RaiseException:
|
|
26
25
|
Enabled: true
|
|
27
26
|
Lint/StructNewOverride:
|
|
28
27
|
Enabled: true
|
|
28
|
+
Metrics/AbcSize:
|
|
29
|
+
Enabled: false
|
|
29
30
|
Metrics/BlockLength:
|
|
30
31
|
Exclude:
|
|
31
32
|
- 'spec/**/**/*'
|
|
@@ -38,11 +39,15 @@ RSpec/ExampleLength:
|
|
|
38
39
|
Enabled: false
|
|
39
40
|
RSpec/MultipleExpectations:
|
|
40
41
|
Enabled: false
|
|
42
|
+
RSpec/NoExpectationExample:
|
|
43
|
+
Enabled: false
|
|
41
44
|
Style/ArgumentsForwarding:
|
|
42
45
|
Enabled: false
|
|
43
46
|
Style/Documentation:
|
|
44
47
|
Enabled: false
|
|
45
48
|
Style/ExpandPathArguments:
|
|
46
49
|
Enabled: false
|
|
50
|
+
Style/StringLiterals:
|
|
51
|
+
EnforcedStyle: double_quotes
|
|
47
52
|
Style/StructInheritance:
|
|
48
53
|
Enabled: false
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.1.0] - 2022-11-17
|
|
10
|
+
### Changed
|
|
11
|
+
- Improved docs
|
|
12
|
+
- Updated internal setup
|
|
13
|
+
- Improved rubocop setup
|
|
14
|
+
|
|
15
|
+
## [1.0.1] - 2021-09-09
|
|
16
|
+
### Changed
|
|
17
|
+
- Remove snail dependency
|
|
18
|
+
|
|
9
19
|
## [1.0.0] - 2021-09-09
|
|
10
20
|
### Added
|
|
11
21
|
- Initial project version
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,85 +1,69 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
lite-address (1.
|
|
4
|
+
lite-address (1.1.0)
|
|
5
5
|
countries
|
|
6
|
-
snail
|
|
7
6
|
|
|
8
7
|
GEM
|
|
9
8
|
remote: https://rubygems.org/
|
|
10
9
|
specs:
|
|
11
|
-
activesupport (6.1.4.1)
|
|
12
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
13
|
-
i18n (>= 1.6, < 2)
|
|
14
|
-
minitest (>= 5.1)
|
|
15
|
-
tzinfo (~> 2.0)
|
|
16
|
-
zeitwerk (~> 2.3)
|
|
17
10
|
ast (2.4.2)
|
|
18
11
|
colorize (0.8.1)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
diff-lcs (1.4.4)
|
|
24
|
-
fasterer (0.9.0)
|
|
12
|
+
countries (5.2.0)
|
|
13
|
+
unaccent (~> 0.3)
|
|
14
|
+
diff-lcs (1.5.0)
|
|
15
|
+
fasterer (0.10.0)
|
|
25
16
|
colorize (~> 0.7)
|
|
26
|
-
ruby_parser (>= 3.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
minitest (5.14.4)
|
|
31
|
-
parallel (1.20.2)
|
|
32
|
-
parser (3.0.2.0)
|
|
17
|
+
ruby_parser (>= 3.19.1)
|
|
18
|
+
json (2.6.2)
|
|
19
|
+
parallel (1.22.1)
|
|
20
|
+
parser (3.1.2.1)
|
|
33
21
|
ast (~> 2.4.1)
|
|
34
|
-
rainbow (3.
|
|
22
|
+
rainbow (3.1.1)
|
|
35
23
|
rake (13.0.6)
|
|
36
|
-
regexp_parser (2.
|
|
24
|
+
regexp_parser (2.6.1)
|
|
37
25
|
rexml (3.2.5)
|
|
38
|
-
rspec (3.
|
|
39
|
-
rspec-core (~> 3.
|
|
40
|
-
rspec-expectations (~> 3.
|
|
41
|
-
rspec-mocks (~> 3.
|
|
42
|
-
rspec-core (3.
|
|
43
|
-
rspec-support (~> 3.
|
|
44
|
-
rspec-expectations (3.
|
|
26
|
+
rspec (3.12.0)
|
|
27
|
+
rspec-core (~> 3.12.0)
|
|
28
|
+
rspec-expectations (~> 3.12.0)
|
|
29
|
+
rspec-mocks (~> 3.12.0)
|
|
30
|
+
rspec-core (3.12.0)
|
|
31
|
+
rspec-support (~> 3.12.0)
|
|
32
|
+
rspec-expectations (3.12.0)
|
|
45
33
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
46
|
-
rspec-support (~> 3.
|
|
47
|
-
rspec-mocks (3.
|
|
34
|
+
rspec-support (~> 3.12.0)
|
|
35
|
+
rspec-mocks (3.12.0)
|
|
48
36
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
49
|
-
rspec-support (~> 3.
|
|
50
|
-
rspec-support (3.
|
|
51
|
-
rubocop (1.
|
|
37
|
+
rspec-support (~> 3.12.0)
|
|
38
|
+
rspec-support (3.12.0)
|
|
39
|
+
rubocop (1.39.0)
|
|
40
|
+
json (~> 2.3)
|
|
52
41
|
parallel (~> 1.10)
|
|
53
|
-
parser (>= 3.
|
|
42
|
+
parser (>= 3.1.2.1)
|
|
54
43
|
rainbow (>= 2.2.2, < 4.0)
|
|
55
44
|
regexp_parser (>= 1.8, < 3.0)
|
|
56
|
-
rexml
|
|
57
|
-
rubocop-ast (>= 1.
|
|
45
|
+
rexml (>= 3.2.5, < 4.0)
|
|
46
|
+
rubocop-ast (>= 1.23.0, < 2.0)
|
|
58
47
|
ruby-progressbar (~> 1.7)
|
|
59
48
|
unicode-display_width (>= 1.4.0, < 3.0)
|
|
60
|
-
rubocop-ast (1.
|
|
61
|
-
parser (>= 3.
|
|
62
|
-
rubocop-performance (1.
|
|
49
|
+
rubocop-ast (1.23.0)
|
|
50
|
+
parser (>= 3.1.1.0)
|
|
51
|
+
rubocop-performance (1.15.1)
|
|
63
52
|
rubocop (>= 1.7.0, < 2.0)
|
|
64
53
|
rubocop-ast (>= 0.4.0)
|
|
65
54
|
rubocop-rake (0.6.0)
|
|
66
55
|
rubocop (~> 1.0)
|
|
67
|
-
rubocop-rspec (2.
|
|
68
|
-
rubocop (~> 1.
|
|
69
|
-
rubocop-ast (>= 1.1.0)
|
|
56
|
+
rubocop-rspec (2.15.0)
|
|
57
|
+
rubocop (~> 1.33)
|
|
70
58
|
ruby-progressbar (1.11.0)
|
|
71
|
-
ruby_parser (3.
|
|
72
|
-
sexp_processor (~> 4.
|
|
73
|
-
sexp_processor (4.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
activesupport
|
|
77
|
-
tzinfo (2.0.4)
|
|
78
|
-
concurrent-ruby (~> 1.0)
|
|
79
|
-
unicode-display_width (2.0.0)
|
|
80
|
-
zeitwerk (2.4.2)
|
|
59
|
+
ruby_parser (3.19.1)
|
|
60
|
+
sexp_processor (~> 4.16)
|
|
61
|
+
sexp_processor (4.16.1)
|
|
62
|
+
unaccent (0.4.0)
|
|
63
|
+
unicode-display_width (2.3.0)
|
|
81
64
|
|
|
82
65
|
PLATFORMS
|
|
66
|
+
arm64-darwin-21
|
|
83
67
|
x86_64-darwin-20
|
|
84
68
|
|
|
85
69
|
DEPENDENCIES
|
|
@@ -94,4 +78,4 @@ DEPENDENCIES
|
|
|
94
78
|
rubocop-rspec
|
|
95
79
|
|
|
96
80
|
BUNDLED WITH
|
|
97
|
-
2.
|
|
81
|
+
2.3.26
|
data/README.md
CHANGED
|
@@ -31,8 +31,9 @@ methods below (check the class to see more). If an address cannot be parsed then
|
|
|
31
31
|
will be returned, but partial matches can be returned. All addresses will try to be
|
|
32
32
|
normalized to return a predictable pattern.
|
|
33
33
|
|
|
34
|
+
#### Full matches
|
|
34
35
|
```
|
|
35
|
-
address = Lite::Address::
|
|
36
|
+
address = Lite::Address::Parser.any("1600 Pennsylvania Ave, Washington, DC, 20500")
|
|
36
37
|
address.street #=> Pennsylvania
|
|
37
38
|
address.number #=> 1600
|
|
38
39
|
address.postal_code #=> 20500
|
|
@@ -41,17 +42,14 @@ address.state #=> DC
|
|
|
41
42
|
address.state_name #=> District of Columbia
|
|
42
43
|
address.street_type #=> Ave
|
|
43
44
|
address.intersection? #=> false
|
|
45
|
+
```
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
#### Partial matches
|
|
48
|
+
```
|
|
49
|
+
address = Lite::Address::Parser.any("1600 Pennsylvania Ave")
|
|
46
50
|
address.street #=> Pennsylvania
|
|
47
51
|
address.number #=> 1600
|
|
48
52
|
address.state #=> nil
|
|
49
|
-
|
|
50
|
-
address = Lite::Address::Parse.parse("5904 Richmond Hwy Ste 340 Alexandria VA 22303-1864")
|
|
51
|
-
address.postal_code_ext #=> 1846
|
|
52
|
-
|
|
53
|
-
address = Lite::Address::Parse.parse("5904 Richmond Hwy Ste 340 Alexandria VA 223031864")
|
|
54
|
-
address.postal_code_ext #=> 1846
|
|
55
53
|
```
|
|
56
54
|
|
|
57
55
|
## Formatting
|
|
@@ -59,7 +57,7 @@ address.postal_code_ext #=> 1846
|
|
|
59
57
|
A formatted can be returned to as a whole or in parts of simple strings.
|
|
60
58
|
|
|
61
59
|
```
|
|
62
|
-
address = Lite::Address::
|
|
60
|
+
address = Lite::Address::Parser.any("1600 Pennsylvania Ave, Washington, DC, 20500")
|
|
63
61
|
address.to_s #=> 1600 Pennsylvania Ave, Washington, DC 20500
|
|
64
62
|
address.to_s(:line1) #=> 1600 Pennsylvania Ave
|
|
65
63
|
address.to_s(:line2) #=> Washington, DC 20500
|
|
@@ -67,14 +65,20 @@ address.to_s(:line2) #=> Washington, DC 20500
|
|
|
67
65
|
|
|
68
66
|
You can also format strings to the proper country mail format.
|
|
69
67
|
|
|
68
|
+
#### Address only
|
|
70
69
|
```
|
|
71
|
-
address = Lite::Address::
|
|
72
|
-
address.to_snail
|
|
73
|
-
|
|
70
|
+
address = Lite::Address::Parser.any("1600 Pennsylvania Ave, Washington, DC, 20500")
|
|
71
|
+
address.to_snail #=> 1600 Pennsylvania Ave,
|
|
72
|
+
Washington, DC 20500
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
#### Name prepended
|
|
77
|
+
```
|
|
78
|
+
address = Lite::Address::Parser.any("1600 Pennsylvania Ave, Washington, DC, 20500")
|
|
79
|
+
address.to_snail(name: 'John Doe') #=> John Doe
|
|
80
|
+
1600 Pennsylvania Ave,
|
|
81
|
+
Washington, DC 20500
|
|
78
82
|
```
|
|
79
83
|
|
|
80
84
|
## Development
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
require
|
|
5
|
-
require
|
|
4
|
+
require "bundler/setup"
|
|
5
|
+
require "lite/address"
|
|
6
6
|
|
|
7
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
|
8
8
|
# with your gem easier. You can also use a different console, if you like.
|
|
@@ -11,5 +11,5 @@ require 'lite/address'
|
|
|
11
11
|
# require "pry"
|
|
12
12
|
# Pry.start
|
|
13
13
|
|
|
14
|
-
require
|
|
14
|
+
require "irb"
|
|
15
15
|
IRB.start(__FILE__)
|
data/lib/lite/address/format.rb
CHANGED
|
@@ -1,31 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'snail' unless defined?(Snail)
|
|
4
|
-
|
|
5
3
|
module Lite
|
|
6
4
|
module Address
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
suffix suffix2
|
|
15
|
-
city
|
|
16
|
-
state
|
|
17
|
-
postal_code postal_code_ext
|
|
18
|
-
country list regexp
|
|
19
|
-
].freeze
|
|
20
|
-
|
|
21
|
-
class Format < Struct.new(*FORMAT_KEYS, keyword_init: true)
|
|
6
|
+
PARTS = begin
|
|
7
|
+
file_path = File.expand_path("types/part.yml", File.dirname(__FILE__))
|
|
8
|
+
YAML.load_file(file_path).map(&:to_sym)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class Format < Struct.new(:list, *PARTS, keyword_init: true)
|
|
22
12
|
|
|
23
13
|
def country_code
|
|
24
14
|
country.alpha2
|
|
25
15
|
end
|
|
26
16
|
|
|
27
17
|
def country_name
|
|
28
|
-
country.
|
|
18
|
+
country.iso_short_name
|
|
29
19
|
end
|
|
30
20
|
|
|
31
21
|
def intersection?
|
|
@@ -35,16 +25,16 @@ module Lite
|
|
|
35
25
|
def full_postal_code
|
|
36
26
|
return if postal_code.nil?
|
|
37
27
|
|
|
38
|
-
@full_postal_code ||= [postal_code, postal_code_ext].compact.join(
|
|
28
|
+
@full_postal_code ||= [postal_code, postal_code_ext].compact.join("-")
|
|
39
29
|
end
|
|
40
30
|
|
|
41
|
-
def line1(str = +
|
|
31
|
+
def line1(str = +"")
|
|
42
32
|
parts = intersection? ? intersection_line1 : address_line1
|
|
43
|
-
str + parts.compact.join(
|
|
33
|
+
str + parts.compact.join(" ").strip
|
|
44
34
|
end
|
|
45
35
|
|
|
46
|
-
def line2(str = +
|
|
47
|
-
str += [city, state].compact.join(
|
|
36
|
+
def line2(str = +"")
|
|
37
|
+
str += [city, state].compact.join(", ")
|
|
48
38
|
str << " #{full_postal_code}" if postal_code
|
|
49
39
|
str.strip
|
|
50
40
|
end
|
|
@@ -54,7 +44,7 @@ module Lite
|
|
|
54
44
|
end
|
|
55
45
|
|
|
56
46
|
def to_h
|
|
57
|
-
@to_h ||= Lite::Address::
|
|
47
|
+
@to_h ||= Lite::Address::PARTS.each_with_object({}) do |key, hash|
|
|
58
48
|
hash[key] = public_send(key)
|
|
59
49
|
end
|
|
60
50
|
end
|
|
@@ -63,12 +53,14 @@ module Lite
|
|
|
63
53
|
case format
|
|
64
54
|
when :line1 then line1
|
|
65
55
|
when :line2 then line2
|
|
66
|
-
else [line1, line2].reject(&:empty?).join(
|
|
56
|
+
else [line1, line2].reject(&:empty?).join(", ")
|
|
67
57
|
end
|
|
68
58
|
end
|
|
69
59
|
|
|
70
|
-
def to_snail(
|
|
71
|
-
|
|
60
|
+
def to_snail(prefixes: [], include_country: false)
|
|
61
|
+
prefixes.push(line1, line2)
|
|
62
|
+
prefixes.push(country_name) if include_country
|
|
63
|
+
prefixes.compact.join("\n")
|
|
72
64
|
end
|
|
73
65
|
|
|
74
66
|
def to_ukey
|
|
@@ -84,7 +76,6 @@ module Lite
|
|
|
84
76
|
|
|
85
77
|
private
|
|
86
78
|
|
|
87
|
-
# rubocop:disable Metrics/AbcSize, Naming/VariableNumber
|
|
88
79
|
def address_line1
|
|
89
80
|
parts = []
|
|
90
81
|
parts << number
|
|
@@ -94,34 +85,24 @@ module Lite
|
|
|
94
85
|
parts << suffix
|
|
95
86
|
parts << unit_prefix
|
|
96
87
|
# http://pe.usps.gov/cpim/ftp/pubs/Pub28/pub28.pdf pg28
|
|
97
|
-
parts << (unit_prefix ? unit : "
|
|
88
|
+
parts << (unit_prefix ? unit : "# #{unit}") if unit
|
|
98
89
|
parts
|
|
99
90
|
end
|
|
100
91
|
|
|
101
|
-
def snail_params
|
|
102
|
-
{
|
|
103
|
-
line_1: line1,
|
|
104
|
-
city: city,
|
|
105
|
-
region: state,
|
|
106
|
-
postal_code: full_postal_code,
|
|
107
|
-
country: country_code
|
|
108
|
-
}
|
|
109
|
-
end
|
|
110
|
-
|
|
111
92
|
def intersection_line1
|
|
112
93
|
parts = []
|
|
113
94
|
parts << prefix
|
|
114
95
|
parts << street
|
|
115
96
|
parts << street_type
|
|
116
97
|
parts << suffix
|
|
117
|
-
parts <<
|
|
98
|
+
parts << "and"
|
|
118
99
|
parts << prefix2
|
|
119
100
|
parts << street2
|
|
120
101
|
parts << street_type2
|
|
121
102
|
parts << suffix2
|
|
122
103
|
parts
|
|
123
104
|
end
|
|
124
|
-
# rubocop:enable Metrics/AbcSize
|
|
105
|
+
# rubocop:enable Metrics/AbcSize
|
|
125
106
|
|
|
126
107
|
end
|
|
127
108
|
|
data/lib/lite/address/list.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "yaml" unless defined?(YAML)
|
|
4
4
|
|
|
5
5
|
module Lite
|
|
6
6
|
module Address
|
|
@@ -18,14 +18,14 @@ module Lite
|
|
|
18
18
|
|
|
19
19
|
def cardinal_types
|
|
20
20
|
@cardinal_types ||= begin
|
|
21
|
-
file_path = File.expand_path(
|
|
21
|
+
file_path = File.expand_path("types/cardinal.yml", File.dirname(__FILE__))
|
|
22
22
|
YAML.load_file(file_path)
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def street_types
|
|
27
27
|
@street_types ||= begin
|
|
28
|
-
file_path = File.expand_path(
|
|
28
|
+
file_path = File.expand_path("types/street.yml", File.dirname(__FILE__))
|
|
29
29
|
YAML.load_file(file_path)
|
|
30
30
|
end
|
|
31
31
|
end
|
|
@@ -57,37 +57,37 @@ module Lite
|
|
|
57
57
|
|
|
58
58
|
def unit_abbr_numbered_regexps
|
|
59
59
|
@unit_abbr_numbered_regexps ||= {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
60
|
+
"Apt" => /(?:ap|dep)(?:ar)?t(?:me?nt)?/i,
|
|
61
|
+
"PO Box" => /p\W*[om]\W*b(?:ox)?/i,
|
|
62
|
+
"Bldg" => /bu?i?ldi?n?g/i,
|
|
63
|
+
"Dept" => /dep(artmen)?t/i,
|
|
64
|
+
"Floor" => /flo*r?/i,
|
|
65
|
+
"Hanger" => /ha?nga?r/i,
|
|
66
|
+
"Lot" => /lo?t/i,
|
|
67
|
+
"Room" => /ro*m/i,
|
|
68
|
+
"Pier" => /pier/i,
|
|
69
|
+
"Slip" => /slip/i,
|
|
70
|
+
"Space" => /spa?ce?/i,
|
|
71
|
+
"Stop" => /stop/i,
|
|
72
|
+
"Drawer" => /drawer/i,
|
|
73
|
+
"Suite" => /su?i?te/i,
|
|
74
|
+
"Trailer" => /tra?i?le?r/i,
|
|
75
|
+
"Box" => /\w*(?<!po\W)box/i,
|
|
76
|
+
"Unit" => /uni?t/i
|
|
77
77
|
}
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
def unit_abbr_unnumbered_regexps
|
|
81
81
|
@unit_abbr_unnumbered_regexps ||= {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
"Basement" => /ba?se?me?n?t/i,
|
|
83
|
+
"Front" => /fro?nt/i,
|
|
84
|
+
"Lobby" => /lo?bby/i,
|
|
85
|
+
"Lower" => /lowe?r/i,
|
|
86
|
+
"Office" => /off?i?ce?/i,
|
|
87
|
+
"PH" => /pe?n?t?ho?u?s?e?/i,
|
|
88
|
+
"Rear" => /rear/i,
|
|
89
|
+
"Side" => /side/i,
|
|
90
|
+
"Upper" => /uppe?r/i
|
|
91
91
|
}
|
|
92
92
|
end
|
|
93
93
|
|
data/lib/lite/address/parser.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "countries" unless defined?(ISO3166::Country)
|
|
4
4
|
|
|
5
5
|
module Lite
|
|
6
6
|
module Address
|
|
@@ -8,11 +8,11 @@ module Lite
|
|
|
8
8
|
|
|
9
9
|
LOOKUPS = %i[any formal informal intersectional].freeze
|
|
10
10
|
CAPITALIZATION_PARTS = %w[street street_type street2 street_type2 city unit_prefix].freeze
|
|
11
|
-
STREET_POSITIONS = [
|
|
11
|
+
STREET_POSITIONS = ["", "1", "2"].freeze
|
|
12
12
|
|
|
13
13
|
attr_reader :address, :country_code
|
|
14
14
|
|
|
15
|
-
def initialize(address, country_code:
|
|
15
|
+
def initialize(address, country_code: "US")
|
|
16
16
|
@address = sanitize_address(address)
|
|
17
17
|
@country_code = sanitize_country_code(country_code)
|
|
18
18
|
end
|
|
@@ -21,7 +21,7 @@ module Lite
|
|
|
21
21
|
|
|
22
22
|
LOOKUPS.each do |method_name|
|
|
23
23
|
define_method(method_name) do |address, args = {}|
|
|
24
|
-
instance = new(address, country_code: args.delete(:country_code) ||
|
|
24
|
+
instance = new(address, country_code: args.delete(:country_code) || "US")
|
|
25
25
|
instance.public_send(method_name, args)
|
|
26
26
|
end
|
|
27
27
|
end
|
|
@@ -52,9 +52,9 @@ module Lite
|
|
|
52
52
|
return unless (match = regexp.intersectional_address.match(address))
|
|
53
53
|
|
|
54
54
|
map = match_map(match)
|
|
55
|
-
intersectional_submatch(match, map,
|
|
56
|
-
intersectional_submatch(match, map,
|
|
57
|
-
intersectional_rematch(match, map,
|
|
55
|
+
intersectional_submatch(match, map, "street")
|
|
56
|
+
intersectional_submatch(match, map, "street_type")
|
|
57
|
+
intersectional_rematch(match, map, "street_type")
|
|
58
58
|
|
|
59
59
|
generate_address(map, args)
|
|
60
60
|
end
|
|
@@ -76,7 +76,7 @@ module Lite
|
|
|
76
76
|
private
|
|
77
77
|
|
|
78
78
|
def sanitize_address(value)
|
|
79
|
-
value.delete_prefix(
|
|
79
|
+
value.delete_prefix("(").delete_suffix(")")
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
def sanitize_country_code(value)
|
|
@@ -89,19 +89,18 @@ module Lite
|
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
# rubocop:disable Metrics/AbcSize
|
|
93
92
|
def normalization_map
|
|
94
93
|
@normalization_map ||= {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
94
|
+
"prefix" => list.cardinal_types,
|
|
95
|
+
"prefix1" => list.cardinal_types,
|
|
96
|
+
"prefix2" => list.cardinal_types,
|
|
97
|
+
"suffix" => list.cardinal_types,
|
|
98
|
+
"suffix1" => list.cardinal_types,
|
|
99
|
+
"suffix2" => list.cardinal_types,
|
|
100
|
+
"street_type" => list.street_types,
|
|
101
|
+
"street_type1" => list.street_types,
|
|
102
|
+
"street_type2" => list.street_types,
|
|
103
|
+
"state" => list.subdivision_names
|
|
105
104
|
}
|
|
106
105
|
end
|
|
107
106
|
# rubocop:enable Metrics/AbcSize
|
|
@@ -117,7 +116,7 @@ module Lite
|
|
|
117
116
|
return unless map[part] && (!map["#{part}2"] || (map[part] == map["#{part}2"]))
|
|
118
117
|
|
|
119
118
|
type = map[part].dup
|
|
120
|
-
return unless type.gsub!(/s\W*$/i,
|
|
119
|
+
return unless type.gsub!(/s\W*$/i, "") && (/\A#{regexp.public_send(part)}\z/io =~ type)
|
|
121
120
|
|
|
122
121
|
map[part] = map["#{part}2"] = type
|
|
123
122
|
end
|
|
@@ -126,27 +125,27 @@ module Lite
|
|
|
126
125
|
map.each do |key, string|
|
|
127
126
|
string.strip!
|
|
128
127
|
|
|
129
|
-
if key ==
|
|
130
|
-
string.gsub!(%r{[^\w\s\-\#&/.]},
|
|
128
|
+
if key == "number"
|
|
129
|
+
string.gsub!(%r{[^\w\s\-\#&/.]}, "")
|
|
131
130
|
else
|
|
132
|
-
string.gsub!(%r{[^\w\s\-\#&/]},
|
|
131
|
+
string.gsub!(%r{[^\w\s\-\#&/]}, "")
|
|
133
132
|
end
|
|
134
133
|
end
|
|
135
134
|
end
|
|
136
135
|
|
|
137
136
|
def address_redundantize_street_type(map)
|
|
138
|
-
map[
|
|
139
|
-
return unless map[
|
|
137
|
+
map["redundant_street_type"] = false
|
|
138
|
+
return unless map["street"] && !map["street_type"]
|
|
140
139
|
|
|
141
|
-
match = regexp.street.match(map[
|
|
142
|
-
map[
|
|
143
|
-
map[
|
|
140
|
+
match = regexp.street.match(map["street"])
|
|
141
|
+
map["street_type"] = match["street_type"] if match
|
|
142
|
+
map["redundant_street_type"] = true
|
|
144
143
|
end
|
|
145
144
|
|
|
146
145
|
def address_abbreviate_unit_prefixes(map)
|
|
147
146
|
list.unit_abbr_regexps.each do |abbr, regex|
|
|
148
|
-
regex.match(map[
|
|
149
|
-
map[
|
|
147
|
+
regex.match(map["unit_prefix"]) do |_match|
|
|
148
|
+
map["unit_prefix"] = abbr
|
|
150
149
|
end
|
|
151
150
|
end
|
|
152
151
|
end
|
|
@@ -174,25 +173,25 @@ module Lite
|
|
|
174
173
|
end
|
|
175
174
|
|
|
176
175
|
def address_expand_cardinals(map)
|
|
177
|
-
return unless map[
|
|
176
|
+
return unless map["city"]
|
|
178
177
|
|
|
179
|
-
map[
|
|
178
|
+
map["city"].gsub!(/^(#{regexp.cardinal_code})\s+(?=\S)/o) do |match|
|
|
180
179
|
"#{list.cardinal_codes[match[0].upcase]} "
|
|
181
180
|
end
|
|
182
181
|
end
|
|
183
182
|
|
|
184
183
|
def address_fix_dirty_ordinals(map)
|
|
185
184
|
# Sometimes parcel data will have addresses like "1 1ST ST" as "1 1 ST ST"
|
|
186
|
-
return unless map[
|
|
185
|
+
return unless map["street"]
|
|
187
186
|
|
|
188
|
-
map[
|
|
189
|
-
match.gsub!(/\s+/,
|
|
187
|
+
map["street"].gsub!(/\A(\d+\s+st|\d+\s+nd|\d+\s+rd|\d+\s+th)\z/i) do |match|
|
|
188
|
+
match.gsub!(/\s+/, "")
|
|
190
189
|
end
|
|
191
190
|
end
|
|
192
191
|
|
|
193
192
|
def address_capitalize_parts(map)
|
|
194
193
|
CAPITALIZATION_PARTS.each do |k|
|
|
195
|
-
map[k] = map[k].split.map(&:capitalize).join(
|
|
194
|
+
map[k] = map[k].split.map(&:capitalize).join(" ") if map[k]
|
|
196
195
|
end
|
|
197
196
|
end
|
|
198
197
|
|
|
@@ -206,8 +205,9 @@ module Lite
|
|
|
206
205
|
address_fix_dirty_ordinals(map)
|
|
207
206
|
address_capitalize_parts(map)
|
|
208
207
|
|
|
209
|
-
map
|
|
210
|
-
|
|
208
|
+
map[:country] = country
|
|
209
|
+
|
|
210
|
+
Lite::Address::Format.new(list:, **map)
|
|
211
211
|
end
|
|
212
212
|
|
|
213
213
|
end
|
data/lib/lite/address/regexp.rb
CHANGED
|
@@ -17,7 +17,7 @@ module Lite
|
|
|
17
17
|
def cardinal_code
|
|
18
18
|
@cardinal_code ||= begin
|
|
19
19
|
values = list.cardinal_codes.keys
|
|
20
|
-
::Regexp.new(values.join(
|
|
20
|
+
::Regexp.new(values.join("|"), ::Regexp::IGNORECASE)
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -28,7 +28,7 @@ module Lite
|
|
|
28
28
|
array << [::Regexp.quote(val.gsub(/(\w)/, '\1.')), ::Regexp.quote(val)]
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
::Regexp.new(values.join(
|
|
31
|
+
::Regexp.new(values.join("|"), ::Regexp::IGNORECASE)
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
@@ -113,7 +113,7 @@ module Lite
|
|
|
113
113
|
def street_type
|
|
114
114
|
@street_type ||= begin
|
|
115
115
|
values = (list.street_types.keys + list.street_types.values).uniq
|
|
116
|
-
::Regexp.new(values.join(
|
|
116
|
+
::Regexp.new(values.join("|"), ::Regexp::IGNORECASE)
|
|
117
117
|
end
|
|
118
118
|
end
|
|
119
119
|
|
data/lib/lite/address/ukey.rb
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "digest" unless defined?(Digest)
|
|
4
4
|
|
|
5
5
|
module Lite
|
|
6
6
|
module Address
|
|
7
|
-
|
|
7
|
+
module Ukey
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def generate(value)
|
|
12
|
-
result = value.downcase.gsub(/[^0-9a-z]/i, '')
|
|
13
|
-
Digest::MD5.hexdigest(result)
|
|
14
|
-
end
|
|
9
|
+
module_function
|
|
15
10
|
|
|
11
|
+
def generate(value)
|
|
12
|
+
result = value.downcase.gsub(/[^0-9a-z]/i, "")
|
|
13
|
+
Digest::MD5.hexdigest(result)
|
|
16
14
|
end
|
|
17
15
|
|
|
18
16
|
end
|
data/lib/lite/address/version.rb
CHANGED
data/lib/lite/address.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
require
|
|
8
|
-
require
|
|
3
|
+
require "lite/address/version"
|
|
4
|
+
require "lite/address/ukey"
|
|
5
|
+
require "lite/address/list"
|
|
6
|
+
require "lite/address/regexp"
|
|
7
|
+
require "lite/address/format"
|
|
8
|
+
require "lite/address/parser"
|
data/lite-address.gemspec
CHANGED
|
@@ -1,51 +1,44 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
lib = File.expand_path(
|
|
3
|
+
lib = File.expand_path("../lib", __FILE__)
|
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
|
-
require
|
|
5
|
+
require "lite/address/version"
|
|
6
6
|
|
|
7
7
|
Gem::Specification.new do |spec|
|
|
8
|
-
spec.name =
|
|
8
|
+
spec.name = "lite-address"
|
|
9
9
|
spec.version = Lite::Address::VERSION
|
|
10
|
-
spec.authors = [
|
|
10
|
+
spec.authors = ["Juan Gomez"]
|
|
11
11
|
spec.email = %w[j.gomez@drexed.com]
|
|
12
12
|
|
|
13
|
-
spec.summary =
|
|
14
|
-
spec.homepage =
|
|
15
|
-
spec.license =
|
|
13
|
+
spec.summary = "Parse and normalize street addresses"
|
|
14
|
+
spec.homepage = "http://drexed.github.io/lite-address"
|
|
15
|
+
spec.license = "MIT"
|
|
16
16
|
|
|
17
17
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
|
18
18
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
'source_code_uri' => 'https://github.com/drexed/lite-address'
|
|
25
|
-
)
|
|
26
|
-
else
|
|
27
|
-
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
|
28
|
-
'public gem pushes.'
|
|
29
|
-
end
|
|
19
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
|
20
|
+
spec.metadata["changelog_uri"] = "https://github.com/drexed/lite-address/blob/master/CHANGELOG.md"
|
|
21
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
22
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
|
23
|
+
spec.metadata["source_code_uri"] = "https://github.com/drexed/lite-address"
|
|
30
24
|
|
|
31
25
|
# Specify which files should be added to the gem when it is released.
|
|
32
26
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
33
|
-
spec.files = Dir.chdir(File.expand_path(
|
|
27
|
+
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
|
34
28
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
35
29
|
end
|
|
36
|
-
spec.bindir =
|
|
30
|
+
spec.bindir = "exe"
|
|
37
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
38
32
|
spec.require_paths = %w[lib]
|
|
39
33
|
|
|
40
|
-
spec.add_dependency
|
|
41
|
-
spec.add_dependency 'snail'
|
|
34
|
+
spec.add_dependency "countries"
|
|
42
35
|
|
|
43
|
-
spec.add_development_dependency
|
|
44
|
-
spec.add_development_dependency
|
|
45
|
-
spec.add_development_dependency
|
|
46
|
-
spec.add_development_dependency
|
|
47
|
-
spec.add_development_dependency
|
|
48
|
-
spec.add_development_dependency
|
|
49
|
-
spec.add_development_dependency
|
|
50
|
-
spec.add_development_dependency
|
|
36
|
+
spec.add_development_dependency "bundler"
|
|
37
|
+
spec.add_development_dependency "fasterer"
|
|
38
|
+
spec.add_development_dependency "rake"
|
|
39
|
+
spec.add_development_dependency "rspec"
|
|
40
|
+
spec.add_development_dependency "rubocop"
|
|
41
|
+
spec.add_development_dependency "rubocop-performance"
|
|
42
|
+
spec.add_development_dependency "rubocop-rake"
|
|
43
|
+
spec.add_development_dependency "rubocop-rspec"
|
|
51
44
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lite-address
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Juan Gomez
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-11-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: countries
|
|
@@ -24,20 +24,6 @@ dependencies:
|
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0'
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: snail
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - ">="
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0'
|
|
34
|
-
type: :runtime
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - ">="
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0'
|
|
41
27
|
- !ruby/object:Gem::Dependency
|
|
42
28
|
name: bundler
|
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -177,6 +163,7 @@ files:
|
|
|
177
163
|
- lib/lite/address/parser.rb
|
|
178
164
|
- lib/lite/address/regexp.rb
|
|
179
165
|
- lib/lite/address/types/cardinal.yml
|
|
166
|
+
- lib/lite/address/types/part.yml
|
|
180
167
|
- lib/lite/address/types/street.yml
|
|
181
168
|
- lib/lite/address/ukey.rb
|
|
182
169
|
- lib/lite/address/version.rb
|
|
@@ -184,7 +171,12 @@ files:
|
|
|
184
171
|
homepage: http://drexed.github.io/lite-address
|
|
185
172
|
licenses:
|
|
186
173
|
- MIT
|
|
187
|
-
metadata:
|
|
174
|
+
metadata:
|
|
175
|
+
allowed_push_host: https://rubygems.org
|
|
176
|
+
changelog_uri: https://github.com/drexed/lite-address/blob/master/CHANGELOG.md
|
|
177
|
+
homepage_uri: http://drexed.github.io/lite-address
|
|
178
|
+
rubygems_mfa_required: 'true'
|
|
179
|
+
source_code_uri: https://github.com/drexed/lite-address
|
|
188
180
|
post_install_message:
|
|
189
181
|
rdoc_options: []
|
|
190
182
|
require_paths:
|
|
@@ -200,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
200
192
|
- !ruby/object:Gem::Version
|
|
201
193
|
version: '0'
|
|
202
194
|
requirements: []
|
|
203
|
-
rubygems_version: 3.
|
|
195
|
+
rubygems_version: 3.3.26
|
|
204
196
|
signing_key:
|
|
205
197
|
specification_version: 4
|
|
206
198
|
summary: Parse and normalize street addresses
|