usps_standardizer 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.rdoc +11 -0
- data/lib/usps_standardizer/cache.rb +50 -0
- data/lib/usps_standardizer/configuration.rb +33 -0
- data/lib/usps_standardizer/version.rb +2 -2
- data/lib/usps_standardizer/zip_lookup.rb +25 -4
- data/lib/usps_standardizer.rb +18 -3
- data/spec/usps_standardizer_spec.rb +18 -0
- metadata +10 -8
data/README.rdoc
CHANGED
@@ -5,6 +5,17 @@
|
|
5
5
|
$ require 'usps_standardizer'
|
6
6
|
$ gem install usps_standardizer
|
7
7
|
|
8
|
+
== Configuration
|
9
|
+
|
10
|
+
=== Caching
|
11
|
+
|
12
|
+
It’s a good idea, when relying on any external service, to cache retrieved data.
|
13
|
+
When implemented correctly it improves your app’s response time and stability.
|
14
|
+
It’s easy to cache usps results with USPSStandardizer, just configure a cache store:
|
15
|
+
|
16
|
+
$ USPSStandardizer::Configuration.cache = Redis.new
|
17
|
+
$ USPSStandardizer::Configuration.cache_prefix = "wyw"
|
18
|
+
|
8
19
|
== Usage
|
9
20
|
|
10
21
|
$ result = USPSStandardizer.lookup_for(:address => '6216 eddington drive', :state => 'oh', :city => 'middletown')
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module USPSStandardizer
|
2
|
+
class Cache
|
3
|
+
|
4
|
+
def initialize(store, prefix)
|
5
|
+
@store = store
|
6
|
+
@prefix = prefix
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](url)
|
10
|
+
interpret store[key_for(url)]
|
11
|
+
end
|
12
|
+
|
13
|
+
def []=(url, value)
|
14
|
+
store[key_for(url)] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def expire(url)
|
18
|
+
if url == :all
|
19
|
+
urls.each{ |u| expire(u) }
|
20
|
+
else
|
21
|
+
expire_single_url(url)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :prefix, :store
|
29
|
+
|
30
|
+
def key_for(url)
|
31
|
+
[prefix, url].join
|
32
|
+
end
|
33
|
+
|
34
|
+
def keys
|
35
|
+
store.keys.select{ |k| k.match /^#{prefix}/ and interpret(store[k]) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def urls
|
39
|
+
keys.map{ |k| k[/^#{prefix}(.*)/, 1] }
|
40
|
+
end
|
41
|
+
|
42
|
+
def interpret(value)
|
43
|
+
value == "" ? nil : value
|
44
|
+
end
|
45
|
+
|
46
|
+
def expire_single_url(url)
|
47
|
+
store.del(key_for(url))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module USPSStandardizer
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
def self.options_and_defaults
|
5
|
+
[
|
6
|
+
[:timeout, 5],
|
7
|
+
|
8
|
+
# cache object (must respond to #[], #[]=, and #keys)
|
9
|
+
[:cache, nil],
|
10
|
+
|
11
|
+
# prefix (string) to use for all cache keys
|
12
|
+
[:cache_prefix, "usps:"]
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
# define getters and setters for all configuration settings
|
17
|
+
self.options_and_defaults.each do |option, default|
|
18
|
+
class_eval(<<-END, __FILE__, __LINE__ + 1)
|
19
|
+
|
20
|
+
@@#{option} = default unless defined? @@#{option}
|
21
|
+
|
22
|
+
def self.#{option}
|
23
|
+
@@#{option}
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.#{option}=(obj)
|
27
|
+
@@#{option} = obj
|
28
|
+
end
|
29
|
+
|
30
|
+
END
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -4,6 +4,9 @@ require 'mechanize'
|
|
4
4
|
|
5
5
|
module USPSStandardizer
|
6
6
|
|
7
|
+
#TODO: Change from 'mechanize' to 'net/hhtp'
|
8
|
+
#TODO: Implement 'timeout'
|
9
|
+
|
7
10
|
class ZipLookup
|
8
11
|
|
9
12
|
attr_accessor :address, :state, :city, :zipcode
|
@@ -17,6 +20,12 @@ module USPSStandardizer
|
|
17
20
|
end
|
18
21
|
|
19
22
|
def std_address
|
23
|
+
|
24
|
+
if(cache and response = cache[redis_key(@address)])
|
25
|
+
address, city, state, county, zipcode = response.split('::')
|
26
|
+
return {:address => address, :city => city, :state => state, :county => county, :zipcode => zipcode}
|
27
|
+
end
|
28
|
+
|
20
29
|
return {} unless (content = get_std_address_content)
|
21
30
|
|
22
31
|
content.gsub!(/\t|\n|\r/, '')
|
@@ -26,18 +35,21 @@ module USPSStandardizer
|
|
26
35
|
|
27
36
|
raw_matches.inject({}) do |results, raw_match|
|
28
37
|
if raw_match[0] =~ /mailingIndustryPopup2\(([^\)]*)/i
|
29
|
-
@
|
38
|
+
@r_county = $1.split(',')[1].gsub(/'/, '')
|
30
39
|
end
|
31
40
|
|
32
|
-
@
|
41
|
+
@r_address, city_state_zipcode = Sanitize.clean(raw_match[0],
|
33
42
|
:remove_contents => true,
|
34
43
|
:elements => %w[br]
|
35
44
|
).strip.split('<br>')
|
36
45
|
if city_state_zipcode.sub_nonascii(' ').squeeze!(' ') =~ /^(.*)\s+(\w\w)\s(\d{5})(-\d{4})?/i
|
37
|
-
@
|
46
|
+
@r_city, @r_state, @r_zipcode = $1, $2, $3
|
38
47
|
end
|
39
48
|
|
40
|
-
results = {:address => @
|
49
|
+
results = {:address => @r_address, :city => @r_city, :state => @r_state, :county => @r_county, :zipcode => @r_zipcode}
|
50
|
+
if cache
|
51
|
+
cache[redis_key(@address)] = "#{@r_address}::#{@r_city}::#{@r_state}::#{@r_county}::#{@r_zipcode}"
|
52
|
+
end
|
41
53
|
results
|
42
54
|
end
|
43
55
|
end
|
@@ -56,6 +68,15 @@ module USPSStandardizer
|
|
56
68
|
return false unless @mechanize.page.search('p.mainRed').empty?
|
57
69
|
@mechanize.page.body
|
58
70
|
end
|
71
|
+
|
72
|
+
def cache
|
73
|
+
USPSStandardizer.cache
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
def redis_key(address)
|
78
|
+
address.downcase.gsub(' ', '_')
|
79
|
+
end
|
59
80
|
end
|
60
81
|
end
|
61
82
|
|
data/lib/usps_standardizer.rb
CHANGED
@@ -1,12 +1,27 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
require 'mechanize'
|
3
|
+
|
4
|
+
#TODO: Improve documentation
|
3
5
|
module USPSStandardizer
|
4
6
|
autoload :Version, "usps_standardizer/version"
|
5
7
|
autoload :ZipLookup, "usps_standardizer/zip_lookup"
|
8
|
+
autoload :Configuration, "usps_standardizer/configuration"
|
9
|
+
autoload :Cache, "usps_standardizer/cache"
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
def lookup_for(options, mechanize = Mechanize.new)
|
14
|
+
z = ZipLookup.new(options, mechanize)
|
15
|
+
z.std_address
|
16
|
+
end
|
17
|
+
|
18
|
+
def cache
|
19
|
+
if @cache.nil? and store = Configuration.cache
|
20
|
+
@cache = Cache.new(store, Configuration.cache_prefix)
|
21
|
+
end
|
22
|
+
@cache
|
23
|
+
end
|
6
24
|
|
7
|
-
def self.lookup_for(options, mechanize = Mechanize.new)
|
8
|
-
z = USPSStandardizer::ZipLookup.new(options, mechanize)
|
9
|
-
z.std_address
|
10
25
|
end
|
11
26
|
|
12
27
|
end
|
@@ -6,6 +6,24 @@ describe USPSStandardizer do
|
|
6
6
|
USPSStandardizer::Version::STRING.should match(/^\d+\.\d+\.\d+$/)
|
7
7
|
end
|
8
8
|
|
9
|
+
describe "configuration" do
|
10
|
+
context "cache" do
|
11
|
+
it " should be nil as default" do
|
12
|
+
USPSStandardizer::Configuration.cache.should == nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
context "cache prefix" do
|
16
|
+
it "should be usps: as default" do
|
17
|
+
USPSStandardizer::Configuration.cache_prefix.should == 'usps:'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
context "timeout" do
|
21
|
+
it "should be 5 seconds as default" do
|
22
|
+
USPSStandardizer::Configuration.timeout.should == 5
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
9
27
|
it "standards an address on usps website" do
|
10
28
|
result = USPSStandardizer.lookup_for(:address => '6216 eddington drive', :state => 'oh', :city => 'middletown')
|
11
29
|
result[:address].should == '6216 EDDINGTON ST'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: usps_standardizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-31 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mechanize
|
16
|
-
requirement: &
|
16
|
+
requirement: &72995970 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 2.0.1
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *72995970
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: sanitize
|
27
|
-
requirement: &
|
27
|
+
requirement: &72995720 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 2.0.3
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *72995720
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &72995490 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: 2.6.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *72995490
|
47
47
|
description: Ruby class to standardize U.S. postal addresses by referencing the U.S.
|
48
48
|
Postal Service's web site
|
49
49
|
email:
|
@@ -58,6 +58,8 @@ files:
|
|
58
58
|
- README.rdoc
|
59
59
|
- Rakefile
|
60
60
|
- lib/usps_standardizer.rb
|
61
|
+
- lib/usps_standardizer/cache.rb
|
62
|
+
- lib/usps_standardizer/configuration.rb
|
61
63
|
- lib/usps_standardizer/version.rb
|
62
64
|
- lib/usps_standardizer/zip_lookup.rb
|
63
65
|
- spec/fixtures/content.html
|