live_address 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MWU0YjJlMzlmMjJjZTcyNWZjODlkMDE2NzhkMTA5NWEyMzhkN2Q3NA==
5
+ data.tar.gz: !binary |-
6
+ ZDkxYmFhZDkxMzAyMzJlOWY5YTIxODI0MzBiNGZhOTIzZWRhZTYyNw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MWY2ZjlkM2YyYTVlY2M3YWEyZjFjNWFkZjcyMDRmNWM2OWU5OGNmOGQ0YjRk
10
+ MDhlYmI5NTE4YjQ5ZDdiMDUyOTNmZWIzYmZjMGY4YTQyYTlhMDRmMzViOTk2
11
+ ZjQ4NGMyNThlMWRmNTJhOTU5MDYyYmViZWM1NThjOGVjZGZiYWU=
12
+ data.tar.gz: !binary |-
13
+ NWNkNTg5MjI0Mzc1ZTg0YmI0NDhkNjgwZjk0OTE1NmU5N2JhMTA5NDQyZjI3
14
+ MWZjYjA1YjVkMTA0M2Q1MDA2Y2Y3MDU3ZjNhMjA5MzM0ZjVlN2U5YjY3MmJm
15
+ MDY1NmViMzc1NTg3YTM4OTQ3ZjAxYzY2NWZiOGY0NTJiMTJmNDQ=
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in smarty_streets.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Chris Stringer
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.
@@ -0,0 +1,144 @@
1
+ # LiveAddress
2
+
3
+ Ruby gem to perform US address validation by way of a Ruby interface to the [SmartyStreets LiveAddress API](http://smartystreets.com/). Gives you a Ruby DSL to interact with the API and first class Ruby objects from the response. If you need to validate addresses, skip the unmaintained scrap yard of USPS related gems out there and use a more modern solution such as this one. SmartyStreets currently provides 250 free lookups per month. Beyond that they have reasonable pricing.
4
+
5
+ This gem is certainly not the only attempt to wrap this API, although I believe it is the newest one. Check out [smarty_streets](https://github.com/russ/smarty_streets) (a basic wrapper for street address verification) and [smartystreets](https://github.com/centzy/smartystreets) (supports street and ZIP code APIs, batch requests, and all documented fields) which were both around before I created this gem.
6
+
7
+ Where this gem differs from its predecessors is that it attempts to futureproof changes to what the SmartyStreets LiveAddress API returns by dynamically creating the Ruby response objects. This means that if the SmartyStreets decides to add or remove attributes to/from what their API returns, this gem should still "just work".
8
+
9
+ ## Current Version
10
+
11
+ 0.0.2
12
+
13
+ ## Requirements
14
+
15
+ This gem was created and tested with Ruby 1.9.3. It may well work with earlier versions of Ruby but I make no guarantees.
16
+
17
+ ## Installation
18
+
19
+ Add this line to your application's Gemfile:
20
+
21
+ gem 'live_address'
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install live_address
30
+
31
+ ## Usage
32
+
33
+ 1. First things first. You will need to sign up for an account with Smarty Streets. Once you have signed up and logged in you should be able to generate an API key which will give you the Auth ID and Auth Token that you'll need to start using this gem.
34
+ 2. Configure your Rails app to use your credentials with the gem. The suggested approach would be to put this in an initializer. Also be sure to use the raw version of the Auth token and not the encoded one.
35
+
36
+ ```
37
+ LiveAddress.configure do |config|
38
+ config.auth_id = "YOUR AUTH ID"
39
+ config.auth_token = "YOUR AUTH TOKEN"
40
+ end
41
+ ```
42
+
43
+ 3. Use the verify method to request address verification of an address that you submit. The list of valid input fields can be seen [here](http://smartystreets.com/kb/liveaddress-api/rest-endpoint). Note that you can limit the number of results using the optional candidates field. The results are returned as an array of formatted address objects, and a lookup with no results simply returns an empty array.
44
+
45
+ ```
46
+ => address = {
47
+ :city => "bend",
48
+ :state => "oregon",
49
+ :zipcode => "97701",
50
+ :street => "550 NW Franklin Avenue",
51
+ :street2 => "Suite 200"
52
+ }
53
+
54
+ => LiveAddress.verify(address)
55
+
56
+ # [#<LiveAddress::ResponseParser:0x007ffd6c972fe0
57
+ @analysis=
58
+ #<Analysis:0x007ffd6c970830
59
+ @active="Y",
60
+ @dpv_cmra="N",
61
+ @dpv_footnotes="AABB",
62
+ @dpv_match_code="Y",
63
+ @dpv_vacant="N",
64
+ @footnotes="N#">,
65
+ @candidate_index=0,
66
+ @components=
67
+ #<Components:0x007ffd6c9728d8
68
+ @city_name="Bend",
69
+ @delivery_point="50",
70
+ @delivery_point_check_digit="0",
71
+ @plus4_code="2892",
72
+ @primary_number="550",
73
+ @secondary_designator="Ste",
74
+ @secondary_number="200",
75
+ @state_abbreviation="OR",
76
+ @street_name="Franklin",
77
+ @street_predirection="NW",
78
+ @street_suffix="Ave",
79
+ @zipcode="97701">,
80
+ @delivery_line_1="550 NW Franklin Ave Ste 200",
81
+ @delivery_point_barcode="977012892500",
82
+ @input_index=0,
83
+ @last_line="Bend OR 97701-2892",
84
+ @metadata=
85
+ #<Metadata:0x007ffd6c971a28
86
+ @carrier_route="C004",
87
+ @congressional_district="02",
88
+ @county_fips="41017",
89
+ @county_name="Deschutes",
90
+ @dst=true,
91
+ @elot_sequence="0241",
92
+ @elot_sort="A",
93
+ @latitude=44.05722,
94
+ @longitude=-121.31347,
95
+ @precision="Zip9",
96
+ @rdi="Commercial",
97
+ @record_type="H",
98
+ @time_zone="Pacific",
99
+ @utc_offset=-8.0,
100
+ @zip_type="Standard">>]
101
+ ```
102
+
103
+ ## Specs
104
+
105
+ Specs are written using mini-test. Run them like this.
106
+
107
+ ```
108
+ rake
109
+ ```
110
+
111
+ ## TODO
112
+
113
+ * Add support for zip code API
114
+ * Add support for POST requests which would in turn allow for multiple addresses in one submission (batch requests)
115
+
116
+ ## Authors
117
+
118
+ Chris Stringer / [@jcstringer](https://github.com/jcstringer)
119
+
120
+ ## Bugs
121
+
122
+ File an [issue](https://github.com/jcstringer/live_address/issues)
123
+
124
+ ## Contributing
125
+
126
+ 1. Fork it
127
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
128
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
129
+ 4. Push to the branch (`git push origin my-new-feature`)
130
+ 5. Create new Pull Request
131
+
132
+ If you find bugs, have feature requests or questions, please file an issue.
133
+
134
+ ## License
135
+
136
+ Copyright (c) 2013 Chris Stringer
137
+
138
+ MIT License
139
+
140
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
141
+
142
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
143
+
144
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.test_files = FileList['test/lib/live_address/test_*.rb']
8
+ t.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,45 @@
1
+ require 'httparty'
2
+
3
+ require_relative "./live_address/exceptions"
4
+ require_relative "./live_address/version"
5
+ require_relative "./live_address/configuration"
6
+ require_relative "./live_address/address"
7
+ require_relative "./live_address/url_builder"
8
+ require_relative "./live_address/response_parser"
9
+
10
+ module LiveAddress
11
+
12
+ class << self
13
+ attr_accessor :configuration
14
+
15
+ # Pattern inspired by http://robots.thoughtbot.com/mygem-configure-block/
16
+ def configure
17
+ self.configuration = Configuration.new
18
+ yield(configuration)
19
+ end
20
+
21
+ def auth_id
22
+ LiveAddress.configuration.auth_id
23
+ end
24
+
25
+ def auth_token
26
+ LiveAddress.configuration.auth_token
27
+ end
28
+
29
+ def api_endpoint
30
+ LiveAddress.configuration.api_endpoint
31
+ end
32
+
33
+ def verify(options={})
34
+ if self.configuration.auth_id.nil? || self.configuration.auth_token.nil?
35
+ raise LiveAddress::InvalidConfigError
36
+ end
37
+ raise LiveAddress::InvalidArgumentError if options.empty?
38
+ address = Address.new(options)
39
+ url = UrlBuilder.new(address).url
40
+ response = HTTParty.get(url)
41
+ ResponseParser.parse(response)
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,21 @@
1
+ module LiveAddress
2
+ class Address
3
+
4
+ attr_accessor :street, :street2, :secondary, :city, :state, :zipcode, :lastline, :addressee,
5
+ :urbanization, :callback, :candidates
6
+
7
+ def initialize(options)
8
+ set_attributes(options)
9
+ end
10
+
11
+ private
12
+
13
+ def set_attributes(options)
14
+ options.each do |key,value|
15
+ raise LiveAddress::InvalidArgumentError unless respond_to?(key)
16
+ self.send("#{key}=", value)
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,12 @@
1
+ module LiveAddress
2
+ class Configuration
3
+
4
+ attr_accessor :api_endpoint, :auth_id, :auth_token
5
+
6
+ def initialize
7
+ @api_endpoint = 'https://api.smartystreets.com/street-address'
8
+ end
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,10 @@
1
+ module LiveAddress
2
+
3
+ class InvalidConfigError < StandardError; end
4
+ class InvalidArgumentError < StandardError; end
5
+ class BadInputError < StandardError; end
6
+ class AuthorizationError < StandardError; end
7
+ class PaymentRequiredError < StandardError; end
8
+ class InternalServerError < StandardError; end
9
+
10
+ end
@@ -0,0 +1,54 @@
1
+ require 'json'
2
+
3
+ module LiveAddress
4
+
5
+ class ResponseParser
6
+
7
+ def self.parse(response)
8
+ raise BadInputError if response.code == 400
9
+ raise AuthorizationError if response.code == 401
10
+ raise PaymentRequiredError if response.code == 402
11
+ raise InternalServerError if response.code == 500
12
+
13
+ parsed_response = JSON.parse(response.body)
14
+ parsed_response.map {|r| ResponseParser.new(r) }
15
+ end
16
+
17
+ def initialize(response)
18
+ set_attrs(response)
19
+ end
20
+
21
+ private
22
+
23
+ def set_attrs(hash)
24
+ # Dynamically create attrs on the object for each hash key
25
+ # and create subclasses for nested hashes
26
+ hash.each do |key,value|
27
+ symbolized_key = key.to_sym
28
+ define_attr(symbolized_key)
29
+ if value.is_a?(Hash)
30
+ populate_subclass(key, value)
31
+ else
32
+ self.send("#{symbolized_key}=", value)
33
+ end
34
+ end
35
+ end
36
+
37
+ def define_attr(attribute)
38
+ self.class.send(:attr_accessor, attribute)
39
+ end
40
+
41
+ def populate_subclass(attribute, hash)
42
+ klass_name = attribute.capitalize
43
+ if Object.const_defined? klass_name
44
+ klass = Object.const_get klass_name
45
+ else
46
+ klass = Object.const_set klass_name, Class.new(self.class)
47
+ end
48
+ klass.send(:define_method, :initialize) { |args| set_attrs(args) }
49
+ instance_variable_set("@#{attribute}", klass.new(hash))
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,37 @@
1
+ require 'uri'
2
+
3
+ module LiveAddress
4
+
5
+ class UrlBuilder
6
+
7
+ attr_accessor :instance, :url
8
+
9
+ def initialize(instance)
10
+ @instance = instance
11
+ @url = build_url
12
+ end
13
+
14
+ private
15
+
16
+ def build_url
17
+ params = {
18
+ :street => instance.street,
19
+ :street2 => instance.street2,
20
+ :secondary => instance.secondary,
21
+ :city => instance.city,
22
+ :state => instance.state,
23
+ :zipcode => instance.zipcode,
24
+ :lastline => instance.lastline,
25
+ :addressee => instance.addressee,
26
+ :urbanization => instance.urbanization,
27
+ :callback => instance.callback,
28
+ :candidates => instance.candidates,
29
+ :"auth-id" => LiveAddress::auth_id,
30
+ :"auth-token" => LiveAddress::auth_token
31
+ }
32
+ "#{LiveAddress::api_endpoint}?#{URI.encode_www_form(params)}"
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,3 @@
1
+ module LiveAddress
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'live_address/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "live_address"
8
+ spec.version = LiveAddress::VERSION
9
+ spec.authors = ["Chris Stringer"]
10
+ spec.email = ["chris.stringer@g5searchmarketing.com"]
11
+ spec.description = %q{Ruby wrapper for the SmartyStreets LiveAddress API}
12
+ spec.summary = %q{Creates requests and parses responses to/from the SmartyStreets LiveAddress API using Ruby.}
13
+ spec.homepage = "https://github.com/jcstringer/live_address"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
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 "httparty"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "webmock"
26
+ spec.add_development_dependency "vcr"
27
+ spec.add_development_dependency "mocha"
28
+ end
@@ -0,0 +1,142 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.smartystreets.com/street-address?addressee&auth-id=00b81f59-bf87-42a6-ac65-5ea8556cac81&auth-token=mhv7Wy1BLAptSU4eSucbxZYiz2DtdBioQe%2Bq%2BOaFGViRRxx3OFlR5Cc1wShTaS5Yx3cLFF88MsGfKpc2A099yg==&callback&candidates&city=Bend&lastline&secondary&state=OR&street=550%20NW%20Franklin%20Avenue&street2=Suite%20200&urbanization&zipcode=97701
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ Cache-Control:
16
+ - private
17
+ Content-Type:
18
+ - application/json; charset=utf-8
19
+ Server:
20
+ - Microsoft-IIS/7.5
21
+ Access-Control-Allow-Origin:
22
+ - ! '*'
23
+ Access-Control-Allow-Headers:
24
+ - ! '*'
25
+ Access-Control-Allow-Methods:
26
+ - GET, POST, PUT
27
+ X-Powered-By:
28
+ - ASP.NET
29
+ Date:
30
+ - Thu, 26 Dec 2013 19:27:46 GMT
31
+ Content-Length:
32
+ - '908'
33
+ body:
34
+ encoding: US-ASCII
35
+ string: ! '[{"input_index":0,"candidate_index":0,"delivery_line_1":"550 NW Franklin
36
+ Ave Ste 200","last_line":"Bend OR 97701-2892","delivery_point_barcode":"977012892500","components":{"primary_number":"550","street_predirection":"NW","street_name":"Franklin","street_suffix":"Ave","secondary_number":"200","secondary_designator":"Ste","city_name":"Bend","state_abbreviation":"OR","zipcode":"97701","plus4_code":"2892","delivery_point":"50","delivery_point_check_digit":"0"},"metadata":{"record_type":"H","zip_type":"Standard","county_fips":"41017","county_name":"Deschutes","carrier_route":"C004","congressional_district":"02","rdi":"Commercial","elot_sequence":"0241","elot_sort":"A","latitude":44.05722,"longitude":-121.31347,"precision":"Zip9","time_zone":"Pacific","utc_offset":-8.0,"dst":true},"analysis":{"dpv_match_code":"Y","dpv_footnotes":"AABB","dpv_cmra":"N","dpv_vacant":"N","active":"Y","footnotes":"N#"}}]'
37
+ http_version:
38
+ recorded_at: Thu, 26 Dec 2013 19:28:01 GMT
39
+ - request:
40
+ method: get
41
+ uri: https://api.smartystreets.com/street-address?addressee&auth-id=mhv7Wy1BLAptSU4eSucbxZYiz2DtdBioQe%2Bq%2BOaFGViRRxx3OFlR5Cc1wShTaS5Yx3cLFF88MsGfKpc2A099yg==&auth-token=mhv7Wy1BLAptSU4eSucbxZYiz2DtdBioQe%2Bq%2BOaFGViRRxx3OFlR5Cc1wShTaS5Yx3cLFF88MsGfKpc2A099yg==&callback&candidates&city=Bend&lastline&secondary&state=OR&street=550%20NW%20Franklin%20Avenue&street2=Suite%20200&urbanization&zipcode=97701
42
+ body:
43
+ encoding: US-ASCII
44
+ string: ''
45
+ headers: {}
46
+ response:
47
+ status:
48
+ code: 401
49
+ message: Not authenticated.
50
+ headers:
51
+ Server:
52
+ - Microsoft-IIS/7.5
53
+ X-Powered-By:
54
+ - ASP.NET
55
+ Date:
56
+ - Thu, 26 Dec 2013 20:13:31 GMT
57
+ Content-Length:
58
+ - '0'
59
+ body:
60
+ encoding: US-ASCII
61
+ string: ''
62
+ http_version:
63
+ recorded_at: Thu, 26 Dec 2013 20:13:52 GMT
64
+ - request:
65
+ method: get
66
+ uri: https://api.smartystreets.com/street-address?addressee&auth-id=00b81f59-bf87-42a6-ac65-5ea8556cac81&auth-token=mhv7Wy1BLAptSU4eSucbxZYiz2DtdBioQe%2Bq%2BOaFGViRRxx3OFlR5Cc1wShTaS5Yx3cLFF88MsGfKpc2A099yg==&callback&candidates&city=Bend&lastline&secondary&state=OR&street=550%20NW%20Franklin%20Avenue&street2=Ste%20200&urbanization&zipcode=97701
67
+ body:
68
+ encoding: US-ASCII
69
+ string: ''
70
+ headers: {}
71
+ response:
72
+ status:
73
+ code: 200
74
+ message: OK
75
+ headers:
76
+ Cache-Control:
77
+ - private
78
+ Content-Type:
79
+ - application/json; charset=utf-8
80
+ Server:
81
+ - Microsoft-IIS/7.5
82
+ Access-Control-Allow-Origin:
83
+ - ! '*'
84
+ Access-Control-Allow-Headers:
85
+ - ! '*'
86
+ Access-Control-Allow-Methods:
87
+ - GET, POST, PUT
88
+ X-Powered-By:
89
+ - ASP.NET
90
+ Date:
91
+ - Thu, 26 Dec 2013 20:33:52 GMT
92
+ Content-Length:
93
+ - '908'
94
+ body:
95
+ encoding: US-ASCII
96
+ string: ! '[{"input_index":0,"candidate_index":0,"delivery_line_1":"550 NW Franklin
97
+ Ave Ste 200","last_line":"Bend OR 97701-2892","delivery_point_barcode":"977012892500","components":{"primary_number":"550","street_predirection":"NW","street_name":"Franklin","street_suffix":"Ave","secondary_number":"200","secondary_designator":"Ste","city_name":"Bend","state_abbreviation":"OR","zipcode":"97701","plus4_code":"2892","delivery_point":"50","delivery_point_check_digit":"0"},"metadata":{"record_type":"H","zip_type":"Standard","county_fips":"41017","county_name":"Deschutes","carrier_route":"C004","congressional_district":"02","rdi":"Commercial","elot_sequence":"0241","elot_sort":"A","latitude":44.05722,"longitude":-121.31347,"precision":"Zip9","time_zone":"Pacific","utc_offset":-8.0,"dst":true},"analysis":{"dpv_match_code":"Y","dpv_footnotes":"AABB","dpv_cmra":"N","dpv_vacant":"N","active":"Y","footnotes":"N#"}}]'
98
+ http_version:
99
+ recorded_at: Thu, 26 Dec 2013 20:34:22 GMT
100
+ - request:
101
+ method: get
102
+ uri: https://api.smartystreets.com/street-address?addressee&auth-id=00b81f59-bf87-42a6-ac65-5ea8556cac81&auth-token=mhv7Wy1BLAptSU4eSucbxZYiz2DtdBioQe%2Bq%2BOaFGViRRxx3OFlR5Cc1wShTaS5Yx3cLFF88MsGfKpc2A099yg==&callback&candidates&city=bend&lastline&secondary&state=oregon&street=550%20NW%20Franklin%20Avenue&street2=Suite%20200&urbanization&zipcode=97701
103
+ body:
104
+ encoding: US-ASCII
105
+ string: ''
106
+ headers: {}
107
+ response:
108
+ status:
109
+ code: 200
110
+ message: OK
111
+ headers:
112
+ Cache-Control:
113
+ - private
114
+ Content-Type:
115
+ - application/json; charset=utf-8
116
+ Server:
117
+ - Microsoft-IIS/7.5
118
+ Access-Control-Allow-Origin:
119
+ - ! '*'
120
+ Access-Control-Allow-Headers:
121
+ - ! '*'
122
+ Access-Control-Allow-Methods:
123
+ - GET, POST, PUT
124
+ X-Powered-By:
125
+ - ASP.NET
126
+ Date:
127
+ - Sat, 28 Dec 2013 00:05:45 GMT
128
+ Content-Length:
129
+ - '908'
130
+ Connection:
131
+ - Keep-alive
132
+ Keep-Alive:
133
+ - timeout=15, max=100
134
+ Via:
135
+ - 1.1 ID-0002262046133470 uproxy-6
136
+ body:
137
+ encoding: US-ASCII
138
+ string: ! '[{"input_index":0,"candidate_index":0,"delivery_line_1":"550 NW Franklin
139
+ Ave Ste 200","last_line":"Bend OR 97701-2892","delivery_point_barcode":"977012892500","components":{"primary_number":"550","street_predirection":"NW","street_name":"Franklin","street_suffix":"Ave","secondary_number":"200","secondary_designator":"Ste","city_name":"Bend","state_abbreviation":"OR","zipcode":"97701","plus4_code":"2892","delivery_point":"50","delivery_point_check_digit":"0"},"metadata":{"record_type":"H","zip_type":"Standard","county_fips":"41017","county_name":"Deschutes","carrier_route":"C004","congressional_district":"02","rdi":"Commercial","elot_sequence":"0241","elot_sort":"A","latitude":44.05722,"longitude":-121.31347,"precision":"Zip9","time_zone":"Pacific","utc_offset":-8.0,"dst":true},"analysis":{"dpv_match_code":"Y","dpv_footnotes":"AABB","dpv_cmra":"N","dpv_vacant":"N","active":"Y","footnotes":"N#"}}]'
140
+ http_version:
141
+ recorded_at: Sat, 28 Dec 2013 00:05:46 GMT
142
+ recorded_with: VCR 2.5.0
@@ -0,0 +1,174 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.smartystreets.com/street-address?addressee&auth-id=00b81f59-bf87-42a6-ac65-5ea8556cac81&auth-token=mhv7Wy1BLAptSU4eSucbxZYiz2DtdBioQe%2Bq%2BOaFGViRRxx3OFlR5Cc1wShTaS5Yx3cLFF88MsGfKpc2A099yg==&callback&candidates&city=Bend&lastline&secondary&state=OR&street=1234%20not%20real%20street&street2=Suite%20200&urbanization&zipcode=97701
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ Cache-Control:
16
+ - private
17
+ Content-Type:
18
+ - application/json; charset=utf-8
19
+ Server:
20
+ - Microsoft-IIS/7.5
21
+ Access-Control-Allow-Origin:
22
+ - ! '*'
23
+ Access-Control-Allow-Headers:
24
+ - ! '*'
25
+ Access-Control-Allow-Methods:
26
+ - GET, POST, PUT
27
+ X-Powered-By:
28
+ - ASP.NET
29
+ Date:
30
+ - Thu, 26 Dec 2013 19:31:59 GMT
31
+ Content-Length:
32
+ - '2'
33
+ body:
34
+ encoding: US-ASCII
35
+ string: ! '[]'
36
+ http_version:
37
+ recorded_at: Thu, 26 Dec 2013 19:32:14 GMT
38
+ - request:
39
+ method: get
40
+ uri: https://api.smartystreets.com/street-address?addressee&auth-id=mhv7Wy1BLAptSU4eSucbxZYiz2DtdBioQe%2Bq%2BOaFGViRRxx3OFlR5Cc1wShTaS5Yx3cLFF88MsGfKpc2A099yg==&auth-token=mhv7Wy1BLAptSU4eSucbxZYiz2DtdBioQe%2Bq%2BOaFGViRRxx3OFlR5Cc1wShTaS5Yx3cLFF88MsGfKpc2A099yg==&callback&candidates&city=Bend&lastline&secondary&state=OR&street=1234%20not%20real%20street&street2=Suite%20200&urbanization&zipcode=97701
41
+ body:
42
+ encoding: US-ASCII
43
+ string: ''
44
+ headers: {}
45
+ response:
46
+ status:
47
+ code: 401
48
+ message: Not authenticated.
49
+ headers:
50
+ Server:
51
+ - Microsoft-IIS/7.5
52
+ X-Powered-By:
53
+ - ASP.NET
54
+ Date:
55
+ - Thu, 26 Dec 2013 20:13:36 GMT
56
+ Content-Length:
57
+ - '0'
58
+ body:
59
+ encoding: US-ASCII
60
+ string: ''
61
+ http_version:
62
+ recorded_at: Thu, 26 Dec 2013 20:13:52 GMT
63
+ - request:
64
+ method: get
65
+ uri: https://api.smartystreets.com/street-address?addressee&auth-id=00b81f59-bf87-42a6-ac65-5ea8556cac81&auth-token=mhv7Wy1BLAptSU4eSucbxZYiz2DtdBioQe%2Bq%2BOaFGViRRxx3OFlR5Cc1wShTaS5Yx3cLFF88MsGfKpc2A099yg==&callback&candidates&city=Bend&lastline&secondary&state=OR&street=1234%20not%20real%20street&street2=Ste%20200&urbanization&zipcode=97701
66
+ body:
67
+ encoding: US-ASCII
68
+ string: ''
69
+ headers: {}
70
+ response:
71
+ status:
72
+ code: 200
73
+ message: OK
74
+ headers:
75
+ Cache-Control:
76
+ - private
77
+ Content-Type:
78
+ - application/json; charset=utf-8
79
+ Server:
80
+ - Microsoft-IIS/7.5
81
+ Access-Control-Allow-Origin:
82
+ - ! '*'
83
+ Access-Control-Allow-Headers:
84
+ - ! '*'
85
+ Access-Control-Allow-Methods:
86
+ - GET, POST, PUT
87
+ X-Powered-By:
88
+ - ASP.NET
89
+ Date:
90
+ - Thu, 26 Dec 2013 20:33:52 GMT
91
+ Content-Length:
92
+ - '2'
93
+ body:
94
+ encoding: US-ASCII
95
+ string: ! '[]'
96
+ http_version:
97
+ recorded_at: Thu, 26 Dec 2013 20:34:21 GMT
98
+ - request:
99
+ method: get
100
+ uri: https://api.smartystreets.com/street-address?addressee&auth-id=00b81f59-bf87-42a6-ac65-5ea8556cac81&auth-token=mhv7Wy1BLAptSU4eSucbxZYiz2DtdBioQe%2Bq%2BOaFGViRRxx3OFlR5Cc1wShTaS5Yx3cLFF88MsGfKpc2A099yg==&callback&candidates&city=Bend&lastline&secondary&state=OR&street=1234%20not%20real%20street&street2=Suite%20200&urbanization&zipcode=9999999
101
+ body:
102
+ encoding: US-ASCII
103
+ string: ''
104
+ headers: {}
105
+ response:
106
+ status:
107
+ code: 200
108
+ message: OK
109
+ headers:
110
+ Cache-Control:
111
+ - private
112
+ Content-Type:
113
+ - application/json; charset=utf-8
114
+ Server:
115
+ - Microsoft-IIS/7.5
116
+ Access-Control-Allow-Origin:
117
+ - ! '*'
118
+ Access-Control-Allow-Headers:
119
+ - ! '*'
120
+ Access-Control-Allow-Methods:
121
+ - GET, POST, PUT
122
+ X-Powered-By:
123
+ - ASP.NET
124
+ Date:
125
+ - Fri, 27 Dec 2013 19:57:54 GMT
126
+ Content-Length:
127
+ - '2'
128
+ body:
129
+ encoding: US-ASCII
130
+ string: ! '[]'
131
+ http_version:
132
+ recorded_at: Fri, 27 Dec 2013 19:58:11 GMT
133
+ - request:
134
+ method: get
135
+ uri: https://api.smartystreets.com/street-address?addressee&auth-id=00b81f59-bf87-42a6-ac65-5ea8556cac81&auth-token=mhv7Wy1BLAptSU4eSucbxZYiz2DtdBioQe%2Bq%2BOaFGViRRxx3OFlR5Cc1wShTaS5Yx3cLFF88MsGfKpc2A099yg==&callback&candidates&city=bend&lastline&secondary&state=oregon&street=1234%20not%20real%20street&street2=Suite%20200&urbanization&zipcode=9999999
136
+ body:
137
+ encoding: US-ASCII
138
+ string: ''
139
+ headers: {}
140
+ response:
141
+ status:
142
+ code: 200
143
+ message: OK
144
+ headers:
145
+ Cache-Control:
146
+ - private
147
+ Content-Type:
148
+ - application/json; charset=utf-8
149
+ Server:
150
+ - Microsoft-IIS/7.5
151
+ Access-Control-Allow-Origin:
152
+ - ! '*'
153
+ Access-Control-Allow-Headers:
154
+ - ! '*'
155
+ Access-Control-Allow-Methods:
156
+ - GET, POST, PUT
157
+ X-Powered-By:
158
+ - ASP.NET
159
+ Date:
160
+ - Sat, 28 Dec 2013 00:05:41 GMT
161
+ Content-Length:
162
+ - '2'
163
+ Connection:
164
+ - Keep-alive
165
+ Keep-Alive:
166
+ - timeout=15, max=100
167
+ Via:
168
+ - 1.1 ID-0002262046133470 uproxy-5
169
+ body:
170
+ encoding: US-ASCII
171
+ string: ! '[]'
172
+ http_version:
173
+ recorded_at: Sat, 28 Dec 2013 00:05:46 GMT
174
+ recorded_with: VCR 2.5.0
@@ -0,0 +1,139 @@
1
+ require_relative '../../test_helper'
2
+ require "ostruct"
3
+
4
+ describe LiveAddress do
5
+
6
+ subject { LiveAddress }
7
+
8
+ before do
9
+ subject.configure do |config|
10
+ # These credentials are no longer valid, they were deleted after the VCR cassettes were recorded
11
+ config.auth_id = "00b81f59-bf87-42a6-ac65-5ea8556cac81"
12
+ config.auth_token = "mhv7Wy1BLAptSU4eSucbxZYiz2DtdBioQe+q+OaFGViRRxx3OFlR5Cc1wShTaS5Yx3cLFF88MsGfKpc2A099yg=="
13
+ end
14
+ end
15
+
16
+ describe "config" do
17
+
18
+ it "has an auth id" do
19
+ subject.must_respond_to(:auth_id)
20
+ end
21
+
22
+ it "has an auth token" do
23
+ subject.must_respond_to(:auth_token)
24
+ end
25
+
26
+ it "has an api endpoint" do
27
+ subject.must_respond_to(:api_endpoint)
28
+ end
29
+ end
30
+
31
+ describe "verify" do
32
+
33
+ describe "exceptions" do
34
+
35
+ it "auth_id is not present" do
36
+ subject.configure { |config| config.auth_id = nil }
37
+ proc {
38
+ subject.verify(:foo => "bar")
39
+ }.must_raise(LiveAddress::InvalidConfigError)
40
+ end
41
+
42
+ it "auth_token is not present" do
43
+ subject.configure { |config| config.auth_token = nil }
44
+ proc {
45
+ subject.verify(:foo => "bar")
46
+ }.must_raise(LiveAddress::InvalidConfigError)
47
+ end
48
+
49
+ it "invalid options are passed" do
50
+ proc {
51
+ subject.verify(:foo => "bar")
52
+ }.must_raise(LiveAddress::InvalidArgumentError)
53
+ end
54
+
55
+ it "no options are passed" do
56
+ proc {
57
+ subject.verify
58
+ }.must_raise(LiveAddress::InvalidArgumentError)
59
+ end
60
+
61
+ describe "response codes" do
62
+ it "status 400" do
63
+ HTTParty.stubs(:get).returns(OpenStruct.new(:code => 400))
64
+ proc {
65
+ subject.verify(:candidates => 1)
66
+ }.must_raise(LiveAddress::BadInputError)
67
+ end
68
+
69
+ it "status 401" do
70
+ HTTParty.stubs(:get).returns(OpenStruct.new(:code => 401))
71
+ proc {
72
+ subject.verify(:candidates => 1)
73
+ }.must_raise(LiveAddress::AuthorizationError)
74
+ end
75
+
76
+ it "status 402" do
77
+ HTTParty.stubs(:get).returns(OpenStruct.new(:code => 402))
78
+ proc {
79
+ subject.verify(:candidates => 1)
80
+ }.must_raise(LiveAddress::PaymentRequiredError)
81
+ end
82
+
83
+ it "status 500" do
84
+ HTTParty.stubs(:get).returns(OpenStruct.new(:code => 500))
85
+ proc {
86
+ subject.verify(:candidates => 1)
87
+ }.must_raise(LiveAddress::InternalServerError)
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "requests" do
93
+ let(:options) {
94
+ {
95
+ :city => "bend",
96
+ :state => "oregon",
97
+ :zipcode => "97701",
98
+ :street => "550 NW Franklin Avenue",
99
+ :street2 => "Suite 200"
100
+ }
101
+ }
102
+
103
+ after do
104
+ VCR.eject_cassette
105
+ end
106
+
107
+ describe "invalid address" do
108
+ before do
109
+ VCR.insert_cassette 'invalid_address', :record => :new_episodes
110
+ end
111
+
112
+ it "returns an empty array when the address has no results" do
113
+ options.merge!(:street => "1234 not real street", :zipcode => "9999999")
114
+ subject.verify(options).must_equal []
115
+ end
116
+ end
117
+
118
+ describe "valid addresss" do
119
+ let (:results) { subject.verify(options) }
120
+
121
+ before do
122
+ VCR.insert_cassette 'address', :record => :new_episodes
123
+ end
124
+
125
+ it "returns an array of results" do
126
+ results.must_be_instance_of(Array)
127
+ end
128
+
129
+ it "returns objects with a formatted address" do
130
+ result = results.first
131
+ result.delivery_line_1.must_equal("550 NW Franklin Ave Ste 200")
132
+ result.last_line.must_equal("Bend OR 97701-2892")
133
+ end
134
+
135
+ end
136
+ end
137
+ end
138
+
139
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../../test_helper'
2
+
3
+ describe LiveAddress do
4
+
5
+ it "must be defined" do
6
+ LiveAddress::VERSION.wont_be_nil
7
+ end
8
+
9
+ end
@@ -0,0 +1,11 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/pride'
3
+ require "mocha/setup"
4
+ require 'webmock/minitest'
5
+ require 'vcr'
6
+ require File.expand_path('../../lib/live_address.rb', __FILE__)
7
+
8
+ VCR.configure do |c|
9
+ c.cassette_library_dir = 'test/cassettes'
10
+ c.hook_into :webmock
11
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: live_address
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Chris Stringer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '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.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: vcr
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mocha
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Ruby wrapper for the SmartyStreets LiveAddress API
98
+ email:
99
+ - chris.stringer@g5searchmarketing.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - Gemfile
106
+ - LICENSE.txt
107
+ - README.md
108
+ - Rakefile
109
+ - lib/live_address.rb
110
+ - lib/live_address/address.rb
111
+ - lib/live_address/configuration.rb
112
+ - lib/live_address/exceptions.rb
113
+ - lib/live_address/response_parser.rb
114
+ - lib/live_address/url_builder.rb
115
+ - lib/live_address/version.rb
116
+ - live_address.gemspec
117
+ - test/cassettes/address.yml
118
+ - test/cassettes/invalid_address.yml
119
+ - test/lib/live_address/test_live_address.rb
120
+ - test/lib/live_address/test_version.rb
121
+ - test/test_helper.rb
122
+ homepage: https://github.com/jcstringer/live_address
123
+ licenses:
124
+ - MIT
125
+ metadata: {}
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubyforge_project:
142
+ rubygems_version: 2.1.11
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: Creates requests and parses responses to/from the SmartyStreets LiveAddress
146
+ API using Ruby.
147
+ test_files:
148
+ - test/cassettes/address.yml
149
+ - test/cassettes/invalid_address.yml
150
+ - test/lib/live_address/test_live_address.rb
151
+ - test/lib/live_address/test_version.rb
152
+ - test/test_helper.rb