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 CHANGED
@@ -5,4 +5,5 @@ pkg/*
5
5
  .rvmrc
6
6
  *~
7
7
  docs
8
+ .idea/
8
9
 
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
@@ -1,8 +1,8 @@
1
1
  module USPSStandardizer
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 1
5
- PATCH = 2
4
+ MINOR = 2
5
+ PATCH = 0
6
6
  STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
7
  end
8
8
  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
- @county = $1.split(',')[1].gsub(/'/, '')
38
+ @r_county = $1.split(',')[1].gsub(/'/, '')
30
39
  end
31
40
 
32
- @address, city_state_zipcode = Sanitize.clean(raw_match[0],
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
- @city, @state, @zipcode = $1, $2, $3
46
+ @r_city, @r_state, @r_zipcode = $1, $2, $3
38
47
  end
39
48
 
40
- results = {:address => @address, :city => @city, :state => @state, :county => @county, :zipcode => @zipcode}
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
 
@@ -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.1.2
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-17 00:00:00.000000000Z
12
+ date: 2011-10-31 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mechanize
16
- requirement: &71382600 !ruby/object:Gem::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: *71382600
24
+ version_requirements: *72995970
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sanitize
27
- requirement: &71382350 !ruby/object:Gem::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: *71382350
35
+ version_requirements: *72995720
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &71382120 !ruby/object:Gem::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: *71382120
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