Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add po box and rural route parsing, and valid?

  • Loading branch information...
commit ad7774d45ffb544a9eb4093e5ca2ed2868fa6241 1 parent 337f793
@dcleven authored
View
1  .gitignore
@@ -2,3 +2,4 @@
.bundle
.rvmrc
Gemfile.lock
+pkg/
View
57 lib/people_places_things/street_address.rb
@@ -1,7 +1,7 @@
require 'pry'
module PeoplePlacesThings
class StreetAddress
- attr_accessor :number, :pre_direction, :ordinal, :name, :suffix, :post_direction, :unit_type, :unit, :raw
+ attr_accessor :number, :pre_direction, :ordinal, :name, :suffix, :post_direction, :unit_type, :unit, :po_box, :raw
def initialize(str)
self.raw = str
@@ -21,9 +21,15 @@ def initialize(str)
if self.unit_type
self.unit = tokens[-1]
tokens.slice!(tokens.size - 2, 2)
+ if tokens.size > 0
+ # see if unit_type is specified twice i.e. Suite #
+ if StreetAddress.find_token(tokens[-1], UNIT_TYPES)
+ tokens.slice!(tokens.size - 1)
+ end
+ end
end
end
-
+
# If at least one token remains, check last token for directionality. If so, set post_direction and delete the token
#
if tokens.size > 0
@@ -34,7 +40,7 @@ def initialize(str)
end
end
- # If at least one token remains, check last token for suffix. If so, self set.suffix and delete the token
+ # If at least one token remains, check last token for suffix. If so, set suffix and delete the token
#
if tokens.size > 0
self.suffix = StreetAddress.find_token(tokens[-1], SUFFIXES)
@@ -55,8 +61,14 @@ def initialize(str)
tokens.shift if self.ordinal
end
+ # Check for a PO Box pattern and extract the po_box
+ if tokens.size > 2 && self.number == nil && (tokens.join(' ') =~ PO_BOX_PATTERN || tokens.join(' ') =~ RR_PATTERN)
+ self.po_box = tokens[-1]
+ tokens.slice!(tokens.size - 1)
+ end
+
# if any tokens remain, set joined remaining tokens as name, otherwise, set name to post_direction, if set, and set post_direction to nil
- #
+ #
if tokens.size > 0
self.name = tokens.join(' ')
else
@@ -67,12 +79,18 @@ def initialize(str)
validate_parts
end
+ # check for a valid street address, we assume at least a number or po_box and name is required.
+ def valid?
+ !self.name.nil? && !(self.number.nil? && self.po_box.nil?)
+ end
+
def to_s
parts = []
parts << self.number if self.number
parts << DIRECTIONS[self.pre_direction].first if self.pre_direction
parts << ORDINALS[self.ordinal].first if self.ordinal
parts << self.name if self.name
+ parts << self.po_box if self.po_box
parts << SUFFIXES[self.suffix].first if self.suffix
parts << DIRECTIONS[self.post_direction].first if self.post_direction
parts << UNIT_TYPES[self.unit_type].first if self.unit_type
@@ -80,17 +98,21 @@ def to_s
parts.join(' ')
end
- def to_postal_s
+ # to_canonical_s
+ # format the address in a postal service canonical format
+ def to_canonical_s
parts = []
- parts << self.number if self.number
- parts << StreetAddress.string_for(self.pre_direction, :short) if self.pre_direction
- parts << StreetAddress.string_for(self.ordinal, :short) if self.ordinal
- parts << self.name if self.name
- parts << StreetAddress.string_for(self.suffix, :short) if self.suffix
- parts << StreetAddress.string_for(self.post_direction, :short) if self.post_direction
- parts << StreetAddress.string_for(self.unit_type, :short) if self.unit_type
- parts << StreetAddress.string_for(self.unit, :short) if self.unit
- parts.join(' ')
+ parts << self.number.upcase if self.number
+ parts << StreetAddress.string_for(self.pre_direction, :short).upcase if self.pre_direction
+ parts << StreetAddress.string_for(self.ordinal, :short).upcase if self.ordinal
+ parts << self.name.gsub(/[(,?!\'":.)]/, '').gsub(PO_BOX_PATTERN, 'PO BOX').upcase if self.name
+ parts << self.po_box if self.po_box
+ parts << StreetAddress.string_for(self.suffix, :short).upcase if self.suffix
+ parts << StreetAddress.string_for(self.post_direction, :short).upcase if self.post_direction
+ # make all unit type as the canoncial number "#"
+ parts << StreetAddress.string_for(:number, :short).upcase if self.unit_type
+ parts << self.unit.upcase if self.unit
+ parts.join(' ')
end
def self.string_for(symbol, form)
@@ -124,7 +146,10 @@ def self.find_token(token, values)
nil
end
- # to_postal_s uses the short version of each of the following
+ PO_BOX_PATTERN = /(p.o. box|p o box|post office box|po box)/i
+ RR_PATTERN = /rr[\s*]([#]\d+|\d+)(\s*-\s*|\s*)box[\s*]([#]\d+|\d+)/i
+
+ # to_canonical_s uses the short version of each of the following
# long version is in position 0
# short version is in position 1
@@ -381,7 +406,7 @@ def self.find_token(token, values)
:nineteenth => %w(nineteenth 19th)
}
- # to_postal_s format uses the short form
+ # to_canonical_s format uses the short form
SUPPORTED_FORMS = [:long, :short]
end
end
View
97 spec/people_places_things/street_address_spec.rb
@@ -165,6 +165,11 @@
StreetAddress.string_for(:oaks, :short).should == StreetAddress.string_for(:oaks, :long)
end
+ it "should parse po_box" do
+ addr = StreetAddress.new "PO BOX 111"
+ addr.po_box.should == "111"
+ end
+
it "should handle postal standards" do
addr = StreetAddress.new "100 Back ALY"
addr.suffix.should == :alley
@@ -172,17 +177,101 @@
it "should output postal standard ordinals" do
addr = StreetAddress.new "100 First St"
- addr.to_postal_s.should == "100 1st st"
+ addr.to_canonical_s.should == "100 1ST ST"
end
- it "shoud output postal standard" do
+ it "should output postal standard" do
addr = StreetAddress.new "100 East Woodside Crossing S.W."
- addr.to_postal_s.should == "100 e Woodside xing sw"
+ addr.to_canonical_s.should == "100 E WOODSIDE XING SW"
+ end
+
+ it "should ignore punctuation" do
+ addr = StreetAddress.new %q!100 Avenue of the America's!
+ addr.to_canonical_s.should == %q!100 AVENUE OF THE AMERICAS!
+ end
+
+ it "should output unit as canoncial" do
+ addr = StreetAddress.new %q!100 Main suite 13!
+ addr.to_canonical_s.should == %q!100 MAIN # 13!
+ addr = StreetAddress.new %q!100 Main suite # 13!
+ addr.to_canonical_s.should == %q!100 MAIN # 13!
+ end
+
+ it "should output Rural Route" do
+ addr = StreetAddress.new "RR 3 Box 9"
+ addr.to_canonical_s.should == "RR 3 BOX 9"
+ end
+
+ it "should parse and output PO Box" do
+ addr = StreetAddress.new "P.O. Box 1234"
+ addr.to_canonical_s.should == 'PO BOX 1234'
+ addr.to_s.should == 'P.O. Box 1234'
+
+ addr = StreetAddress.new "Post Office Box 1234"
+ addr.to_canonical_s.should == 'PO BOX 1234'
+ addr.name.should == "Post Office Box"
+ addr.po_box.should == '1234'
+
+ addr = StreetAddress.new "p o Box 1234"
+ addr.to_canonical_s.should == 'PO BOX 1234'
+ addr.name.should == "p o Box"
+ addr.po_box.should == '1234'
+
+ addr = StreetAddress.new "PO Box #1234"
+ addr.to_canonical_s.should == 'PO BOX #1234'
+ addr.name.should == "PO Box"
+ addr.po_box.should == '#1234'
+ end
+
+ it "should handle Number and PO Box" do
+ addr = StreetAddress.new "100 Main P.O. Box 1234"
+ addr.to_canonical_s.should == '100 MAIN PO BOX 1234'
+ addr.to_s.should == '100 Main P.O. Box 1234'
+ end
+
+ it "should ignore whitespace" do
+ addr = StreetAddress.new " 100 E. Woodside "
+ addr.to_canonical_s.should == "100 E WOODSIDE"
end
it "should allow empty" do
addr = StreetAddress.new " "
- addr.to_postal_s.empty?.should == true
+ addr.to_canonical_s.empty?.should == true
+ end
+
+ it "should be valid" do
+ addr = StreetAddress.new "100 main st."
+ addr.valid?.should == true
+
+ addr = StreetAddress.new "PO Box 1234"
+ addr.valid?.should == true
+ end
+
+ it "name without number or number without name should NOT be valid" do
+ addr = StreetAddress.new ""
+ addr.valid?.should == false
+
+ addr = StreetAddress.new "main st."
+ addr.valid?.should == false
+
+ addr = StreetAddress.new "PO Box."
+ addr.valid?.should == false
+
+ addr = StreetAddress.new "100"
+ addr.valid?.should == false
+
+ addr = StreetAddress.new "main st. 100"
+ addr.valid?.should == false
+
+ addr = StreetAddress.new "RR 3 Box 100."
+ addr.valid?.should == true
+
+ addr = StreetAddress.new "RR 3 - Box 100."
+ addr.valid?.should == true
+
+ addr = StreetAddress.new "RR 3 - Box #100."
+ addr.valid?.should == true
+
end
it "should save raw" do
Please sign in to comment.
Something went wrong with that request. Please try again.