smartystreets_ruby_sdk 7.5.0 → 8.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5e49c113cb830c32e70639e9b7aeb1153b22dde346f12047e7f27c31a7b5c46
4
- data.tar.gz: db52d24f0dd8cd9f71296adb65f5531ea55ce8288030347d33446167d0937738
3
+ metadata.gz: 17d2106514bf57a8000b659a859949a5761637e7020b976b7d291d6c2d7a77ca
4
+ data.tar.gz: 9a7c861a9547ae6a412239b1e815c5a31cace855da242bfbd46b2da9a730c4d3
5
5
  SHA512:
6
- metadata.gz: 7c707f24782531ba64d75396693b930444fe05fc7e06ee29b6c2205cf933ee8144d5c28d84710bc4e49a617e65ba5f103acd7c304f507a68c86b2764f90f9185
7
- data.tar.gz: f907ea59300dc08d08ad8514b82a5892f19995a820fa484c5a056bf7174a07334a3342926dafa4adf71d4ab63306ea7f8ac4971a78ea7f447ce7cfb6377bfe4a
6
+ metadata.gz: 42ae40ef8d01607e0310cca3f7b238f702b624bbd0ea88251cb7aa530ce44a91275879f81e4ac0e9cb8a6fc1e4f817346099943d37063a818b42a09476853f56
7
+ data.tar.gz: 14737b02a4f6ec453a087082776b6ece9c7767d583dc459c4963ab66dec041d550d7814b05edc15c248220f963f86ade13f16b4aba264013cd322afb3e7ff329
data/Makefile CHANGED
@@ -37,7 +37,7 @@ us_autocomplete_pro_api:
37
37
  cd examples && ruby us_autocomplete_pro_example.rb
38
38
 
39
39
  us_enrichment_api:
40
- cd examples && ruby us_enrichment_example.rb
40
+ cd examples && ruby us_enrichment_example.rb && ruby us_enrichment_business_example.rb && ruby us_enrichment_etag_example.rb
41
41
 
42
42
  us_extract_api:
43
43
  cd examples && ruby us_extract_example.rb
@@ -0,0 +1,72 @@
1
+ require '../lib/smartystreets_ruby_sdk/static_credentials'
2
+ require '../lib/smartystreets_ruby_sdk/shared_credentials'
3
+ require '../lib/smartystreets_ruby_sdk/basic_auth_credentials'
4
+ require '../lib/smartystreets_ruby_sdk/client_builder'
5
+ require '../lib/smartystreets_ruby_sdk/us_enrichment/lookup'
6
+
7
+ class USEnrichmentBusinessExample
8
+ def run
9
+ id = ENV['SMARTY_AUTH_ID']
10
+ token = ENV['SMARTY_AUTH_TOKEN']
11
+ credentials = SmartyStreets::BasicAuthCredentials.new(id, token)
12
+
13
+ client = SmartyStreets::ClientBuilder.new(credentials).build_us_enrichment_api_client
14
+
15
+ smarty_key = "1962995076"
16
+
17
+ begin
18
+ summary_results = client.send_business_lookup(smarty_key)
19
+ rescue SmartyStreets::SmartyError => err
20
+ puts err
21
+ return
22
+ end
23
+
24
+ if summary_results.nil? || summary_results.empty?
25
+ puts "No response returned for SmartyKey #{smarty_key}"
26
+ return
27
+ end
28
+
29
+ summary = summary_results[0]
30
+ if summary.businesses.nil? || summary.businesses.empty?
31
+ puts "SmartyKey #{smarty_key} has no business tenants"
32
+ return
33
+ end
34
+
35
+ puts "Summary results for SmartyKey: #{smarty_key}"
36
+ summary.businesses.each do |biz|
37
+ puts " - #{biz.company_name} (ID: #{biz.business_id})"
38
+ end
39
+
40
+ first = summary.businesses[0]
41
+ puts
42
+ puts "Fetching details for business: #{first.company_name} (ID: #{first.business_id})"
43
+
44
+ begin
45
+ detail_result = client.send_business_detail_lookup(first.business_id)
46
+ rescue SmartyStreets::SmartyError => err
47
+ puts err
48
+ return
49
+ end
50
+
51
+ if detail_result.nil?
52
+ puts "No detail result returned"
53
+ return
54
+ end
55
+
56
+ puts
57
+ puts "Detail result:"
58
+ puts " smarty_key: #{detail_result.smarty_key}"
59
+ puts " data_set_name: #{detail_result.data_set_name}"
60
+ puts " business_id: #{detail_result.business_id}"
61
+ attrs = detail_result.attributes
62
+ return if attrs.nil?
63
+ attrs.instance_variables.each do |var|
64
+ value = attrs.instance_variable_get(var)
65
+ next if value.nil?
66
+ puts " #{var.to_s.delete('@')}: #{value}"
67
+ end
68
+ end
69
+ end
70
+
71
+ example = USEnrichmentBusinessExample.new
72
+ example.run
@@ -0,0 +1,122 @@
1
+ require '../lib/smartystreets_ruby_sdk/static_credentials'
2
+ require '../lib/smartystreets_ruby_sdk/shared_credentials'
3
+ require '../lib/smartystreets_ruby_sdk/basic_auth_credentials'
4
+ require '../lib/smartystreets_ruby_sdk/client_builder'
5
+ require '../lib/smartystreets_ruby_sdk/us_enrichment/lookup'
6
+
7
+ class USEnrichmentEtagExample
8
+ def run
9
+ id = ENV['SMARTY_AUTH_ID']
10
+ token = ENV['SMARTY_AUTH_TOKEN']
11
+ credentials = SmartyStreets::BasicAuthCredentials.new(id, token)
12
+
13
+ @client = SmartyStreets::ClientBuilder.new(credentials).build_us_enrichment_api_client
14
+ smarty_key = "1962995076"
15
+
16
+ business_id = exercise_summary_etag(smarty_key)
17
+ return if business_id.nil?
18
+
19
+ exercise_detail_etag(business_id)
20
+ end
21
+
22
+ def exercise_summary_etag(smarty_key)
23
+ puts "=== Business.Summary ETag round trip ==="
24
+
25
+ first = SmartyStreets::USEnrichment::Lookup.new(smarty_key, 'business')
26
+ begin
27
+ initial_results = @client.send_business_lookup(first)
28
+ rescue SmartyStreets::SmartyError => err
29
+ puts " Initial Summary call failed: #{err.message}"
30
+ return nil
31
+ end
32
+ captured_etag = first.response_etag
33
+ puts " Call 1 (no Etag): captured Etag=#{display(captured_etag)}, results=#{initial_results.nil? ? 0 : initial_results.length}"
34
+
35
+ if captured_etag.nil? || captured_etag.empty?
36
+ puts " Server did not return an Etag header; skipping conditional calls."
37
+ return first_business_id(initial_results)
38
+ end
39
+
40
+ second = SmartyStreets::USEnrichment::Lookup.new(smarty_key, 'business')
41
+ second.request_etag = captured_etag
42
+ begin
43
+ @client.send_business_lookup(second)
44
+ puts " Call 2 (matching Etag): 200 - server did NOT honor the conditional. Etag=#{display(second.response_etag)}"
45
+ rescue SmartyStreets::NotModifiedInfo => ex
46
+ puts " Call 2 (matching Etag): 304 NotModifiedInfo - caller treats this as cache-valid. Refreshed Etag=#{display(ex.response_etag)}"
47
+ rescue SmartyStreets::SmartyError => err
48
+ puts " Call 2 unexpected failure: #{err.class}: #{err.message}"
49
+ return nil
50
+ end
51
+
52
+ third = SmartyStreets::USEnrichment::Lookup.new(smarty_key, 'business')
53
+ third.request_etag = captured_etag + "X"
54
+ begin
55
+ @client.send_business_lookup(third)
56
+ puts " Call 3 (mutated Etag): 200 as expected. Etag=#{display(third.response_etag)}"
57
+ rescue SmartyStreets::NotModifiedInfo
58
+ puts " Call 3 (mutated Etag): 304 - UNEXPECTED. Server treated a different Etag as matching."
59
+ rescue SmartyStreets::SmartyError => err
60
+ puts " Call 3 unexpected failure: #{err.class}: #{err.message}"
61
+ end
62
+
63
+ first_business_id(initial_results)
64
+ end
65
+
66
+ def exercise_detail_etag(business_id)
67
+ puts
68
+ puts "=== Business.Detail ETag round trip (businessId: #{business_id}) ==="
69
+
70
+ first = SmartyStreets::USEnrichment::BusinessDetailLookup.new(business_id)
71
+ begin
72
+ initial_result = @client.send_business_detail_lookup(first)
73
+ rescue SmartyStreets::SmartyError => err
74
+ puts " Initial Detail call failed: #{err.message}"
75
+ return
76
+ end
77
+ captured_etag = first.response_etag
78
+ puts " Call 1 (no Etag): captured Etag=#{display(captured_etag)}, businessId=#{initial_result ? initial_result.business_id : '<nil>'}"
79
+
80
+ if captured_etag.nil? || captured_etag.empty?
81
+ puts " Server did not return an Etag header; skipping conditional calls."
82
+ return
83
+ end
84
+
85
+ second = SmartyStreets::USEnrichment::BusinessDetailLookup.new(business_id)
86
+ second.request_etag = captured_etag
87
+ begin
88
+ @client.send_business_detail_lookup(second)
89
+ puts " Call 2 (matching Etag): 200 - server did NOT honor the conditional. Etag=#{display(second.response_etag)}"
90
+ rescue SmartyStreets::NotModifiedInfo => ex
91
+ puts " Call 2 (matching Etag): 304 NotModifiedInfo - caller treats this as cache-valid. Refreshed Etag=#{display(ex.response_etag)}"
92
+ rescue SmartyStreets::SmartyError => err
93
+ puts " Call 2 unexpected failure: #{err.class}: #{err.message}"
94
+ return
95
+ end
96
+
97
+ third = SmartyStreets::USEnrichment::BusinessDetailLookup.new(business_id)
98
+ third.request_etag = captured_etag + "X"
99
+ begin
100
+ @client.send_business_detail_lookup(third)
101
+ puts " Call 3 (mutated Etag): 200 as expected. Etag=#{display(third.response_etag)}"
102
+ rescue SmartyStreets::NotModifiedInfo
103
+ puts " Call 3 (mutated Etag): 304 - UNEXPECTED. Server treated a different Etag as matching."
104
+ rescue SmartyStreets::SmartyError => err
105
+ puts " Call 3 unexpected failure: #{err.class}: #{err.message}"
106
+ end
107
+ end
108
+
109
+ def first_business_id(summary_results)
110
+ return nil if summary_results.nil? || summary_results.empty?
111
+ first = summary_results[0]
112
+ return nil if first.businesses.nil? || first.businesses.empty?
113
+ first.businesses[0].business_id
114
+ end
115
+
116
+ def display(value)
117
+ value.nil? || value.empty? ? "<none>" : value
118
+ end
119
+ end
120
+
121
+ example = USEnrichmentEtagExample.new
122
+ example.run
@@ -5,14 +5,11 @@ require '../lib/smartystreets_ruby_sdk/client_builder'
5
5
  require '../lib/smartystreets_ruby_sdk/us_enrichment/lookup'
6
6
 
7
7
  class USEnrichmentAddressExample
8
- def run
9
- # key = 'Your SmartyStreets Auth Key here'
10
- # referer = 'Your host name here'
11
- # We recommend storing your secret keys in environment variables instead---it's safer!
12
- # key = ENV['SMARTY_AUTH_WEB']
13
- # referer = ENV['SMARTY_AUTH_REFERER']
14
- # credentials = SmartyStreets::SharedCredentials.new(key, referer)
8
+ # SmartyKey used for the non-property datasets. The property example uses a
9
+ # separate key because its address happens to have rich financial history.
10
+ SHARED_SMARTY_KEY = '325023201'
15
11
 
12
+ def run
16
13
  id = ENV['SMARTY_AUTH_ID']
17
14
  token = ENV['SMARTY_AUTH_TOKEN']
18
15
  credentials = SmartyStreets::BasicAuthCredentials.new(id, token)
@@ -23,114 +20,167 @@ class USEnrichmentAddressExample
23
20
  #
24
21
  # To try with a proxy, add this method call at the end of the chain
25
22
  # with_proxy('localhost', 8080, 'proxyUser', 'proxyPassword')
26
- client = SmartyStreets::ClientBuilder.new(credentials).
27
- build_us_enrichment_api_client
28
- result = nil
29
-
30
- # Create a new lookup instance to search with address components
31
- lookup = SmartyStreets::USEnrichment::Lookup.new
23
+ @client = SmartyStreets::ClientBuilder.new(credentials).
24
+ build_us_enrichment_api_client
25
+
26
+ property_principal_example
27
+ geo_reference_example
28
+ risk_example
29
+ secondary_example
30
+ secondary_count_example
31
+ end
32
32
 
33
- lookup.smarty_key = "87844267"
34
- lookup.street = "56 Union Ave"
35
- lookup.city = "Somerville"
36
- lookup.state = "NJ"
37
- lookup.zipcode = "08876"
38
- lookup.features = "financial"
39
- # lookup.etag = "AUBAGDQDAIGQYCYC"
33
+ # ---------- property / principal ----------
34
+ def property_principal_example
35
+ banner 'property / principal'
40
36
 
37
+ lookup = SmartyStreets::USEnrichment::Lookup.new
38
+ lookup.smarty_key = '87844267'
39
+ lookup.street = '56 Union Ave'
40
+ lookup.city = 'Somerville'
41
+ lookup.state = 'NJ'
42
+ lookup.zipcode = '08876'
43
+ lookup.features = 'financial'
44
+ # lookup.request_etag = 'AUBAGDQDAIGQYCYC'
41
45
  # lookup.add_custom_parameter('parameter', 'value')
42
46
 
43
- # Or, create a freeform lookup to search using a single line address
44
- freeform_lookup = SmartyStreets::USEnrichment::Lookup.new
45
- freeform_lookup.freeform = "56 Union Ave Somerville NJ 08876"
47
+ results = invoke { @client.send_property_principal_lookup(lookup) }
48
+ return if results.nil? || results.empty?
46
49
 
47
- begin
48
- # Send a lookup with a smarty key using the line below
49
- # result = client.send_property_principal_lookup("325023201")
50
+ response = results[0]
51
+ attrs = response.attributes
52
+ puts "Smarty Key: #{response.smarty_key}"
53
+ puts "Data Set: #{response.data_set_name}/#{response.data_subset_name}"
54
+ puts "ETag: #{lookup.response_etag}"
55
+ puts
56
+ puts 'Property Address:'
57
+ puts " Full Address: #{attrs.property_address_full}"
58
+ puts " City: #{attrs.property_address_city}, #{attrs.property_address_state} #{attrs.property_address_zipcode}"
59
+ puts "Owner: #{attrs.owner_full_name}"
60
+ puts "Year Built: #{attrs.year_built} Building Sqft: #{attrs.building_sqft}"
61
+ puts "Assessed Value: #{attrs.assessed_value} Total Market Value: #{attrs.total_market_value}"
62
+ unless attrs.financial_history.nil? || attrs.financial_history.empty?
63
+ puts "Financial History entries: #{attrs.financial_history.length}"
64
+ end
65
+ end
50
66
 
51
- # Uncomment the following lines to perform other types of lookups:
52
- result = client.send_property_principal_lookup(lookup) # Using address components
53
- # result = client.send_property_principal_lookup(freeform_lookup) # Using freeform address
67
+ # ---------- geo-reference ----------
68
+ def geo_reference_example
69
+ banner 'geo-reference'
54
70
 
55
- # Access the other Enrichment datasets using the below functions. All of these functions can take a lookup or a smartykey
56
- # result = client.send_geo_reference_lookup("325023201")
57
- # result = client.send_risk_lookup("325023201")
58
- # result = client.send_secondary_lookup("325023201")
59
- # result = client.send_secondary_count_lookup("325023201")
71
+ lookup = SmartyStreets::USEnrichment::Lookup.new(SHARED_SMARTY_KEY)
72
+ results = invoke { @client.send_geo_reference_lookup(lookup) }
73
+ return if results.nil? || results.empty?
60
74
 
61
- rescue SmartyStreets::SmartyError => err
62
- puts err
63
- return
64
- end
75
+ response = results[0]
76
+ attrs = response.attributes
77
+ puts "Smarty Key: #{response.smarty_key}"
78
+ puts "Data Set: #{response.data_set_name} (version: #{response.data_set_version})"
79
+ puts "Matched Address: #{response.matched_address}"
80
+ puts "ETag: #{lookup.response_etag}"
81
+ puts
82
+ print_object('Census Block', attrs.census_block)
83
+ print_object('Census County Division', attrs.census_county_division)
84
+ print_object('Census Tract', attrs.census_tract)
85
+ print_object('Core Based Stat Area', attrs.core_based_stat_area)
86
+ print_object('Place', attrs.place)
87
+ end
65
88
 
66
- if result.empty?
67
- puts 'No results. This means the smartykey is not valid.'
68
- return
69
- end
89
+ # ---------- risk ----------
90
+ def risk_example
91
+ banner 'risk'
70
92
 
71
- puts "Lookup Successful! Here is the result:"
72
- puts
93
+ lookup = SmartyStreets::USEnrichment::Lookup.new(SHARED_SMARTY_KEY)
94
+ results = invoke { @client.send_risk_lookup(lookup) }
95
+ return if results.nil? || results.empty?
73
96
 
74
- response = result[0]
97
+ response = results[0]
75
98
  attrs = response.attributes
76
-
77
99
  puts "Smarty Key: #{response.smarty_key}"
78
- puts "Data Set: #{response.data_set_name}/#{response.data_subset_name}"
79
- puts "ETag: #{response.etag}"
100
+ puts "Data Set: #{response.data_set_name}"
101
+ puts "Matched Address: #{response.matched_address}"
102
+ puts "ETag: #{lookup.response_etag}"
80
103
  puts
104
+ puts "Overall Risk: rating=#{attrs.RISK_RATNG} score=#{attrs.RISK_SCORE} spctl=#{attrs.RISK_SPCTL} value=#{attrs.RISK_VALUE}"
105
+ puts "Resilience: rating=#{attrs.RESL_RATNG} score=#{attrs.RESL_SCORE} value=#{attrs.RESL_VALUE}"
106
+ puts "Expected Loss: rating=#{attrs.EAL_RATNG} score=#{attrs.EAL_SCORE} value=#{attrs.EAL_VALT}"
107
+ puts "Geography: county=#{attrs.COUNTY} state=#{attrs.STATE} (#{attrs.STATEABBRV}) tract=#{attrs.TRACT}"
108
+ end
81
109
 
82
- puts "Property Address:"
83
- puts "\tFull Address: #{attrs.property_address_full}"
84
- puts "\tCity: #{attrs.property_address_city}"
85
- puts "\tState: #{attrs.property_address_state}"
86
- puts "\tZIP: #{attrs.property_address_zipcode}"
87
- puts
110
+ # ---------- secondary ----------
111
+ def secondary_example
112
+ banner 'secondary'
88
113
 
89
- puts "Owner:"
90
- puts "\tName: #{attrs.owner_full_name}"
91
- puts "\tOccupancy: #{attrs.owner_occupancy_status}"
92
- puts
114
+ lookup = SmartyStreets::USEnrichment::Lookup.new(SHARED_SMARTY_KEY)
115
+ results = invoke { @client.send_secondary_lookup(lookup) }
116
+ return if results.nil? || results.empty?
93
117
 
94
- puts "Property Details:"
95
- puts "\tLand Use: #{attrs.land_use_standard}"
96
- puts "\tYear Built: #{attrs.year_built}"
97
- puts "\tBuilding Sqft: #{attrs.building_sqft}"
98
- puts "\tLot Sqft: #{attrs.lot_sqft}"
99
- puts "\tAcres: #{attrs.acres}"
100
- puts "\tBathrooms: #{attrs.bathrooms_total}"
101
- puts "\tBedrooms: #{attrs.bedrooms}"
102
- puts "\tStories: #{attrs.stories_number}"
103
- puts "\tFireplace: #{attrs.fireplace}"
104
- puts "\tGarage: #{attrs.garage}"
118
+ response = results[0]
119
+ puts "Smarty Key: #{response.smarty_key}"
120
+ puts "Matched Address: #{response.matched_address}"
121
+ puts "ETag: #{lookup.response_etag}"
105
122
  puts
123
+ print_object('Root Address', response.root_address)
106
124
 
107
- puts "Assessment:"
108
- puts "\tAssessed Value: #{attrs.assessed_value}"
109
- puts "\tTotal Market Value: #{attrs.total_market_value}"
110
- puts "\tTax Year: #{attrs.tax_assess_year}"
111
- puts "\tTax Billed: #{attrs.tax_billed_amount}"
112
- puts
125
+ unless response.aliases.nil? || response.aliases.empty?
126
+ puts "\nAliases (#{response.aliases.length}):"
127
+ response.aliases.each_with_index { |a, i| puts " [#{i}] #{one_liner(a)}" }
128
+ end
129
+
130
+ unless response.secondaries.nil? || response.secondaries.empty?
131
+ puts "\nSecondaries (#{response.secondaries.length}):"
132
+ response.secondaries.first(5).each_with_index { |s, i| puts " [#{i}] #{one_liner(s)}" }
133
+ puts " ...#{response.secondaries.length - 5} more" if response.secondaries.length > 5
134
+ end
135
+ end
136
+
137
+ # ---------- secondary / count ----------
138
+ def secondary_count_example
139
+ banner 'secondary / count'
140
+
141
+ lookup = SmartyStreets::USEnrichment::Lookup.new(SHARED_SMARTY_KEY)
142
+ results = invoke { @client.send_secondary_count_lookup(lookup) }
143
+ return if results.nil? || results.empty?
113
144
 
114
- puts "Location:"
115
- puts "\tCounty: #{attrs.situs_county}"
116
- puts "\tLatitude: #{attrs.latitude}"
117
- puts "\tLongitude: #{attrs.longitude}"
118
- puts "\tElevation (ft): #{attrs.elevation_feet}"
145
+ response = results[0]
146
+ puts "Smarty Key: #{response.smarty_key}"
147
+ puts "Matched Address: #{response.matched_address}"
148
+ puts "Count: #{response.count}"
149
+ puts "ETag: #{lookup.response_etag}"
150
+ end
151
+
152
+ # ---------- helpers ----------
153
+ def banner(title)
119
154
  puts
155
+ puts "=== #{title} ==="
156
+ end
120
157
 
121
- unless attrs.financial_history.nil? || attrs.financial_history.empty?
122
- puts "Financial History (#{attrs.financial_history.length} entries):"
123
- attrs.financial_history.each_with_index do |entry, i|
124
- puts "\tEntry #{i + 1}:"
125
- puts "\t\tDocument Type: #{entry.document_type_description}"
126
- puts "\t\tLender: #{entry.lender_name}"
127
- puts "\t\tMortgage Amount: #{entry.mortgage_amount}"
128
- puts "\t\tMortgage Type: #{entry.mortgage_type}"
129
- puts "\t\tRecording Date: #{entry.mortgage_recording_date}"
130
- end
158
+ def invoke
159
+ yield
160
+ rescue SmartyStreets::SmartyError => err
161
+ puts " Lookup failed: #{err.class}: #{err.message}"
162
+ nil
163
+ end
164
+
165
+ def print_object(label, obj)
166
+ puts "#{label}:"
167
+ if obj.nil?
168
+ puts ' (none)'
169
+ return
170
+ end
171
+ obj.instance_variables.each do |var|
172
+ value = obj.instance_variable_get(var)
173
+ next if value.nil?
174
+ puts " #{var.to_s.delete('@')}: #{value}"
131
175
  end
132
176
  end
177
+
178
+ def one_liner(obj)
179
+ obj.instance_variables.filter_map do |var|
180
+ value = obj.instance_variable_get(var)
181
+ "#{var.to_s.delete('@')}=#{value}" unless value.nil?
182
+ end.join(' ')
183
+ end
133
184
  end
134
185
 
135
- example = USEnrichmentAddressExample.new
136
- example.run
186
+ USEnrichmentAddressExample.new.run
@@ -4,6 +4,12 @@ module SmartyStreets
4
4
  end
5
5
 
6
6
  class NotModifiedInfo < SmartyError
7
+ attr_reader :response_etag
8
+
9
+ def initialize(message = nil, response_etag = nil)
10
+ super(message)
11
+ @response_etag = response_etag
12
+ end
7
13
  end
8
14
 
9
15
  class BadCredentialsError < SmartyError
@@ -8,5 +8,18 @@ module SmartyStreets
8
8
  @header = header
9
9
  @error = error
10
10
  end
11
+
12
+ # Case-insensitive lookup that works on both plain Hash (used by mocks)
13
+ # and Net::HTTPResponse (returned by the live HTTP transport, which
14
+ # exposes each_header but not each_pair).
15
+ def find_header(name)
16
+ return nil if @header.nil?
17
+ target = name.to_s.downcase
18
+ iterator = @header.respond_to?(:each_header) ? :each_header : :each_pair
19
+ @header.send(iterator) do |k, v|
20
+ return v if k.to_s.downcase == target
21
+ end
22
+ nil
23
+ end
11
24
  end
12
25
  end
@@ -18,6 +18,8 @@ module SmartyStreets
18
18
  response
19
19
  end
20
20
 
21
+ private
22
+
21
23
  def parse_rate_limit_response(response)
22
24
  error_message = ""
23
25
  if !response.payload.nil?
@@ -35,8 +37,8 @@ module SmartyStreets
35
37
 
36
38
  def assign_exception(response)
37
39
  response.error = case response.status_code
38
- when '304'
39
- NotModifiedInfo.new(NOT_MODIFIED)
40
+ when '304'
41
+ NotModifiedInfo.new(NOT_MODIFIED, response.find_header('etag'))
40
42
  when '401'
41
43
  BadCredentialsError.new(BAD_CREDENTIALS)
42
44
  when '402'
@@ -0,0 +1,241 @@
1
+ module SmartyStreets
2
+ module USEnrichment
3
+ module Business
4
+ module Detail
5
+ class Attributes
6
+ attr_reader :accounting_expense_range, :accounting_expense_total, :advertising_expense_range, :advertising_expense_total, :business_insurance_expense_range, :business_insurance_expense_total
7
+ attr_reader :business_status, :business_type, :carrier_route, :census_block, :census_tract, :city_name
8
+ attr_reader :company_name, :company_name_secondary, :contact_first_name, :contact_full_name, :contact_gender, :contact_last_name
9
+ attr_reader :contact_middle_name, :contact_prefix, :contact_professional_title, :contact_suffix, :core_based_stat_area_code, :core_based_stat_area_name
10
+ attr_reader :corporate_employee_count_range, :corporate_employee_count_total, :county_fips, :county_name, :credit_capacity, :credit_capacity_range
11
+ attr_reader :credit_score, :credit_score_description, :date_of_last_update, :delivery_line_1, :delivery_point, :delivery_point_check_digit
12
+ attr_reader :domestic_foreign_owner_indicator, :ein, :email, :email_available_indicator, :executive_department, :executive_level
13
+ attr_reader :executive_verification_type, :fax, :female_owned_indicator, :foreign_parent_city_name, :foreign_parent_company_name, :foreign_parent_country
14
+ attr_reader :fortune_1000_branches, :fortune_1000_indicator, :fortune_1000_rank, :holding_city_name, :holding_company_name, :holding_id
15
+ attr_reader :holding_state_abbreviation, :home_based_business_indicator, :hq_city_name, :hq_company_name, :hq_id, :hq_number_of_companies
16
+ attr_reader :hq_state_abbreviation, :latitude, :legal_expense_range, :legal_expense_total, :linkage_company_name, :linkage_indicator
17
+ attr_reader :linkage_level, :linkage_type, :location_employee_count, :location_employee_count_range, :location_sales_range, :location_sales_total
18
+ attr_reader :longitude, :mail_score_code, :mail_score_description, :mailing_carrier_route, :mailing_city_name, :mailing_delivery_line_1
19
+ attr_reader :mailing_delivery_point, :mailing_delivery_point_check_digit, :mailing_plus4_code, :mailing_state_abbreviation, :mailing_zipcode, :manufacturing_indicator
20
+ attr_reader :minority_owned_indicator, :minority_type, :naics_01_code, :naics_01_description, :naics_02_code, :naics_02_description
21
+ attr_reader :naics_03_code, :naics_03_description, :naics_04_code, :naics_04_description, :naics_05_code, :naics_05_description
22
+ attr_reader :naics_06_code, :naics_06_description, :new_business_indicator, :non_profit_indicator, :num_of_pcs_range, :num_of_pcs_total
23
+ attr_reader :number_of_years_in_business, :number_of_years_in_business_range, :office_equipment_expense_range, :office_equipment_expense_total, :operating_hours_friday, :operating_hours_monday
24
+ attr_reader :operating_hours_saturday, :operating_hours_sunday, :operating_hours_thursday, :operating_hours_tuesday, :operating_hours_wednesday, :phone
25
+ attr_reader :phone_area_code, :phone_secondary, :phone_toll_free, :plus4_code, :population_range, :precision
26
+ attr_reader :primary_executive_indicator, :primary_number, :primary_sic_2digit_code, :primary_sic_2digit_description, :primary_sic_4digit_code, :primary_sic_4digit_description
27
+ attr_reader :primary_sic_code, :primary_sic_description, :public_indicator, :rdi, :rent_expense_range, :rent_expense_total
28
+ attr_reader :secondary_01_sic_7digit_code, :secondary_01_sic_7digit_description, :secondary_02_sic_7digit_code, :secondary_02_sic_7digit_description, :secondary_03_sic_7digit_code, :secondary_03_sic_7digit_description
29
+ attr_reader :secondary_04_sic_7digit_code, :secondary_04_sic_7digit_description, :secondary_05_sic_7digit_code, :secondary_05_sic_7digit_description, :secondary_designator, :secondary_number
30
+ attr_reader :sectional_center_facility, :small_business_indicator, :source_title, :square_footage, :square_footage_range, :standardized_title
31
+ attr_reader :standardized_title_rank, :state_abbreviation, :stock_exchange, :street_name, :street_postdirection, :street_predirection
32
+ attr_reader :street_suffix, :sub_hq_city_name, :sub_hq_company_name, :sub_hq_id, :sub_hq_number_of_companies, :sub_hq_state_abbreviation
33
+ attr_reader :technology_expense_range, :technology_expense_total, :telecom_expense_range, :telecom_expense_total, :ticker_symbol, :time_zone
34
+ attr_reader :url, :url_facebook, :url_instagram, :url_linkedin, :url_twitter, :url_yelp
35
+ attr_reader :url_youtube, :utilities_expense_range, :utilities_expense_total, :webmail_indicator, :year_current, :year_current_employee_count
36
+ attr_reader :year_established, :year_four_prior, :year_four_prior_employee_count, :year_four_prior_employee_growth, :year_one_prior, :year_one_prior_employee_count
37
+ attr_reader :year_one_prior_employee_growth, :year_three_prior, :year_three_prior_employee_count, :year_three_prior_employee_growth, :year_two_prior, :year_two_prior_employee_count
38
+ attr_reader :year_two_prior_employee_growth, :zipcode
39
+
40
+ def initialize(obj)
41
+ return if obj.nil?
42
+ @accounting_expense_range = obj['accounting_expense_range']
43
+ @accounting_expense_total = obj['accounting_expense_total']
44
+ @advertising_expense_range = obj['advertising_expense_range']
45
+ @advertising_expense_total = obj['advertising_expense_total']
46
+ @business_insurance_expense_range = obj['business_insurance_expense_range']
47
+ @business_insurance_expense_total = obj['business_insurance_expense_total']
48
+ @business_status = obj['business_status']
49
+ @business_type = obj['business_type']
50
+ @carrier_route = obj['carrier_route']
51
+ @census_block = obj['census_block']
52
+ @census_tract = obj['census_tract']
53
+ @city_name = obj['city_name']
54
+ @company_name = obj['company_name']
55
+ @company_name_secondary = obj['company_name_secondary']
56
+ @contact_first_name = obj['contact_first_name']
57
+ @contact_full_name = obj['contact_full_name']
58
+ @contact_gender = obj['contact_gender']
59
+ @contact_last_name = obj['contact_last_name']
60
+ @contact_middle_name = obj['contact_middle_name']
61
+ @contact_prefix = obj['contact_prefix']
62
+ @contact_professional_title = obj['contact_professional_title']
63
+ @contact_suffix = obj['contact_suffix']
64
+ @core_based_stat_area_code = obj['core_based_stat_area_code']
65
+ @core_based_stat_area_name = obj['core_based_stat_area_name']
66
+ @corporate_employee_count_range = obj['corporate_employee_count_range']
67
+ @corporate_employee_count_total = obj['corporate_employee_count_total']
68
+ @county_fips = obj['county_fips']
69
+ @county_name = obj['county_name']
70
+ @credit_capacity = obj['credit_capacity']
71
+ @credit_capacity_range = obj['credit_capacity_range']
72
+ @credit_score = obj['credit_score']
73
+ @credit_score_description = obj['credit_score_description']
74
+ @date_of_last_update = obj['date_of_last_update']
75
+ @delivery_line_1 = obj['delivery_line_1']
76
+ @delivery_point = obj['delivery_point']
77
+ @delivery_point_check_digit = obj['delivery_point_check_digit']
78
+ @domestic_foreign_owner_indicator = obj['domestic_foreign_owner_indicator']
79
+ @ein = obj['ein']
80
+ @email = obj['email']
81
+ @email_available_indicator = obj['email_available_indicator']
82
+ @executive_department = obj['executive_department']
83
+ @executive_level = obj['executive_level']
84
+ @executive_verification_type = obj['executive_verification_type']
85
+ @fax = obj['fax']
86
+ @female_owned_indicator = obj['female_owned_indicator']
87
+ @foreign_parent_city_name = obj['foreign_parent_city_name']
88
+ @foreign_parent_company_name = obj['foreign_parent_company_name']
89
+ @foreign_parent_country = obj['foreign_parent_country']
90
+ @fortune_1000_branches = obj['fortune_1000_branches']
91
+ @fortune_1000_indicator = obj['fortune_1000_indicator']
92
+ @fortune_1000_rank = obj['fortune_1000_rank']
93
+ @holding_city_name = obj['holding_city_name']
94
+ @holding_company_name = obj['holding_company_name']
95
+ @holding_id = obj['holding_id']
96
+ @holding_state_abbreviation = obj['holding_state_abbreviation']
97
+ @home_based_business_indicator = obj['home_based_business_indicator']
98
+ @hq_city_name = obj['hq_city_name']
99
+ @hq_company_name = obj['hq_company_name']
100
+ @hq_id = obj['hq_id']
101
+ @hq_number_of_companies = obj['hq_number_of_companies']
102
+ @hq_state_abbreviation = obj['hq_state_abbreviation']
103
+ @latitude = obj['latitude']
104
+ @legal_expense_range = obj['legal_expense_range']
105
+ @legal_expense_total = obj['legal_expense_total']
106
+ @linkage_company_name = obj['linkage_company_name']
107
+ @linkage_indicator = obj['linkage_indicator']
108
+ @linkage_level = obj['linkage_level']
109
+ @linkage_type = obj['linkage_type']
110
+ @location_employee_count = obj['location_employee_count']
111
+ @location_employee_count_range = obj['location_employee_count_range']
112
+ @location_sales_range = obj['location_sales_range']
113
+ @location_sales_total = obj['location_sales_total']
114
+ @longitude = obj['longitude']
115
+ @mail_score_code = obj['mail_score_code']
116
+ @mail_score_description = obj['mail_score_description']
117
+ @mailing_carrier_route = obj['mailing_carrier_route']
118
+ @mailing_city_name = obj['mailing_city_name']
119
+ @mailing_delivery_line_1 = obj['mailing_delivery_line_1']
120
+ @mailing_delivery_point = obj['mailing_delivery_point']
121
+ @mailing_delivery_point_check_digit = obj['mailing_delivery_point_check_digit']
122
+ @mailing_plus4_code = obj['mailing_plus4_code']
123
+ @mailing_state_abbreviation = obj['mailing_state_abbreviation']
124
+ @mailing_zipcode = obj['mailing_zipcode']
125
+ @manufacturing_indicator = obj['manufacturing_indicator']
126
+ @minority_owned_indicator = obj['minority_owned_indicator']
127
+ @minority_type = obj['minority_type']
128
+ @naics_01_code = obj['naics_01_code']
129
+ @naics_01_description = obj['naics_01_description']
130
+ @naics_02_code = obj['naics_02_code']
131
+ @naics_02_description = obj['naics_02_description']
132
+ @naics_03_code = obj['naics_03_code']
133
+ @naics_03_description = obj['naics_03_description']
134
+ @naics_04_code = obj['naics_04_code']
135
+ @naics_04_description = obj['naics_04_description']
136
+ @naics_05_code = obj['naics_05_code']
137
+ @naics_05_description = obj['naics_05_description']
138
+ @naics_06_code = obj['naics_06_code']
139
+ @naics_06_description = obj['naics_06_description']
140
+ @new_business_indicator = obj['new_business_indicator']
141
+ @non_profit_indicator = obj['non_profit_indicator']
142
+ @num_of_pcs_range = obj['num_of_pcs_range']
143
+ @num_of_pcs_total = obj['num_of_pcs_total']
144
+ @number_of_years_in_business = obj['number_of_years_in_business']
145
+ @number_of_years_in_business_range = obj['number_of_years_in_business_range']
146
+ @office_equipment_expense_range = obj['office_equipment_expense_range']
147
+ @office_equipment_expense_total = obj['office_equipment_expense_total']
148
+ @operating_hours_friday = obj['operating_hours_friday']
149
+ @operating_hours_monday = obj['operating_hours_monday']
150
+ @operating_hours_saturday = obj['operating_hours_saturday']
151
+ @operating_hours_sunday = obj['operating_hours_sunday']
152
+ @operating_hours_thursday = obj['operating_hours_thursday']
153
+ @operating_hours_tuesday = obj['operating_hours_tuesday']
154
+ @operating_hours_wednesday = obj['operating_hours_wednesday']
155
+ @phone = obj['phone']
156
+ @phone_area_code = obj['phone_area_code']
157
+ @phone_secondary = obj['phone_secondary']
158
+ @phone_toll_free = obj['phone_toll_free']
159
+ @plus4_code = obj['plus4_code']
160
+ @population_range = obj['population_range']
161
+ @precision = obj['precision']
162
+ @primary_executive_indicator = obj['primary_executive_indicator']
163
+ @primary_number = obj['primary_number']
164
+ @primary_sic_2digit_code = obj['primary_sic_2digit_code']
165
+ @primary_sic_2digit_description = obj['primary_sic_2digit_description']
166
+ @primary_sic_4digit_code = obj['primary_sic_4digit_code']
167
+ @primary_sic_4digit_description = obj['primary_sic_4digit_description']
168
+ @primary_sic_code = obj['primary_sic_code']
169
+ @primary_sic_description = obj['primary_sic_description']
170
+ @public_indicator = obj['public_indicator']
171
+ @rdi = obj['rdi']
172
+ @rent_expense_range = obj['rent_expense_range']
173
+ @rent_expense_total = obj['rent_expense_total']
174
+ @secondary_01_sic_7digit_code = obj['secondary_01_sic_7digit_code']
175
+ @secondary_01_sic_7digit_description = obj['secondary_01_sic_7digit_description']
176
+ @secondary_02_sic_7digit_code = obj['secondary_02_sic_7digit_code']
177
+ @secondary_02_sic_7digit_description = obj['secondary_02_sic_7digit_description']
178
+ @secondary_03_sic_7digit_code = obj['secondary_03_sic_7digit_code']
179
+ @secondary_03_sic_7digit_description = obj['secondary_03_sic_7digit_description']
180
+ @secondary_04_sic_7digit_code = obj['secondary_04_sic_7digit_code']
181
+ @secondary_04_sic_7digit_description = obj['secondary_04_sic_7digit_description']
182
+ @secondary_05_sic_7digit_code = obj['secondary_05_sic_7digit_code']
183
+ @secondary_05_sic_7digit_description = obj['secondary_05_sic_7digit_description']
184
+ @secondary_designator = obj['secondary_designator']
185
+ @secondary_number = obj['secondary_number']
186
+ @sectional_center_facility = obj['sectional_center_facility']
187
+ @small_business_indicator = obj['small_business_indicator']
188
+ @source_title = obj['source_title']
189
+ @square_footage = obj['square_footage']
190
+ @square_footage_range = obj['square_footage_range']
191
+ @standardized_title = obj['standardized_title']
192
+ @standardized_title_rank = obj['standardized_title_rank']
193
+ @state_abbreviation = obj['state_abbreviation']
194
+ @stock_exchange = obj['stock_exchange']
195
+ @street_name = obj['street_name']
196
+ @street_postdirection = obj['street_postdirection']
197
+ @street_predirection = obj['street_predirection']
198
+ @street_suffix = obj['street_suffix']
199
+ @sub_hq_city_name = obj['sub_hq_city_name']
200
+ @sub_hq_company_name = obj['sub_hq_company_name']
201
+ @sub_hq_id = obj['sub_hq_id']
202
+ @sub_hq_number_of_companies = obj['sub_hq_number_of_companies']
203
+ @sub_hq_state_abbreviation = obj['sub_hq_state_abbreviation']
204
+ @technology_expense_range = obj['technology_expense_range']
205
+ @technology_expense_total = obj['technology_expense_total']
206
+ @telecom_expense_range = obj['telecom_expense_range']
207
+ @telecom_expense_total = obj['telecom_expense_total']
208
+ @ticker_symbol = obj['ticker_symbol']
209
+ @time_zone = obj['time_zone']
210
+ @url = obj['url']
211
+ @url_facebook = obj['url_facebook']
212
+ @url_instagram = obj['url_instagram']
213
+ @url_linkedin = obj['url_linkedin']
214
+ @url_twitter = obj['url_twitter']
215
+ @url_yelp = obj['url_yelp']
216
+ @url_youtube = obj['url_youtube']
217
+ @utilities_expense_range = obj['utilities_expense_range']
218
+ @utilities_expense_total = obj['utilities_expense_total']
219
+ @webmail_indicator = obj['webmail_indicator']
220
+ @year_current = obj['year_current']
221
+ @year_current_employee_count = obj['year_current_employee_count']
222
+ @year_established = obj['year_established']
223
+ @year_four_prior = obj['year_four_prior']
224
+ @year_four_prior_employee_count = obj['year_four_prior_employee_count']
225
+ @year_four_prior_employee_growth = obj['year_four_prior_employee_growth']
226
+ @year_one_prior = obj['year_one_prior']
227
+ @year_one_prior_employee_count = obj['year_one_prior_employee_count']
228
+ @year_one_prior_employee_growth = obj['year_one_prior_employee_growth']
229
+ @year_three_prior = obj['year_three_prior']
230
+ @year_three_prior_employee_count = obj['year_three_prior_employee_count']
231
+ @year_three_prior_employee_growth = obj['year_three_prior_employee_growth']
232
+ @year_two_prior = obj['year_two_prior']
233
+ @year_two_prior_employee_count = obj['year_two_prior_employee_count']
234
+ @year_two_prior_employee_growth = obj['year_two_prior_employee_growth']
235
+ @zipcode = obj['zipcode']
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
241
+ end
@@ -0,0 +1,20 @@
1
+ require_relative 'attributes'
2
+
3
+ module SmartyStreets
4
+ module USEnrichment
5
+ module Business
6
+ module Detail
7
+ class Response
8
+ attr_reader :smarty_key, :data_set_name, :business_id, :attributes
9
+
10
+ def initialize(obj)
11
+ @smarty_key = obj['smarty_key']
12
+ @data_set_name = obj['data_set_name']
13
+ @business_id = obj['business_id']
14
+ @attributes = Attributes.new(obj['attributes'])
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ module SmartyStreets
2
+ module USEnrichment
3
+ module Business
4
+ module Summary
5
+ class BusinessEntry
6
+ attr_reader :company_name, :business_id
7
+
8
+ def initialize(obj)
9
+ @company_name = obj['company_name']
10
+ @business_id = obj['business_id']
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'business_entry'
2
+
3
+ module SmartyStreets
4
+ module USEnrichment
5
+ module Business
6
+ module Summary
7
+ class Response
8
+ attr_reader :smarty_key, :data_set_name, :businesses
9
+
10
+ def initialize(obj)
11
+ @smarty_key = obj['smarty_key']
12
+ @data_set_name = obj['data_set_name']
13
+ @businesses = build_businesses(obj['businesses'])
14
+ end
15
+
16
+ def build_businesses(entries)
17
+ return [] if entries.nil?
18
+ entries.map { |entry| Business::Summary::BusinessEntry.new(entry) }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -3,8 +3,12 @@ require_relative "geo_reference/response"
3
3
  require_relative "risk/response"
4
4
  require_relative "secondary/response"
5
5
  require_relative "secondary/count/response"
6
+ require_relative "business/summary/response"
7
+ require_relative "business/detail/response"
6
8
  require_relative "lookup"
7
9
  require_relative '../request'
10
+ require_relative '../exceptions'
11
+ require 'uri'
8
12
 
9
13
  module SmartyStreets
10
14
  module USEnrichment
@@ -64,6 +68,50 @@ module SmartyStreets
64
68
  end
65
69
  end
66
70
 
71
+ def send_business_lookup(lookup)
72
+ if (lookup.instance_of? String)
73
+ __send(USEnrichment::Lookup.new(lookup,'business'))
74
+ elsif (lookup.instance_of? USEnrichment::Lookup)
75
+ lookup.data_set = 'business'
76
+ lookup.data_sub_set = nil
77
+ __send(lookup)
78
+ end
79
+ end
80
+
81
+ def send_business_detail_lookup(lookup)
82
+ if (lookup.instance_of? String)
83
+ lookup = USEnrichment::BusinessDetailLookup.new(lookup)
84
+ end
85
+ unless lookup.instance_of? USEnrichment::BusinessDetailLookup
86
+ raise SmartyError.new("Business detail lookup requires a non-empty 'business_id'")
87
+ end
88
+ if blank?(lookup.business_id)
89
+ raise SmartyError.new("Business detail lookup requires a non-empty 'business_id'")
90
+ end
91
+
92
+ smarty_request = Request.new
93
+ smarty_request.url_components = '/business/' + encode_path_segment(lookup.business_id)
94
+ apply_common_request_fields(smarty_request, lookup)
95
+
96
+ response = @sender.send(smarty_request)
97
+ capture_response_etag(response, lookup)
98
+ results = @serializer.deserialize(response.payload)
99
+
100
+ results = [] if results.nil?
101
+ raise response.error if response.error
102
+
103
+ if results.length > 1
104
+ raise SmartyError.new("Business detail response contained #{results.length} results; expected at most 1")
105
+ end
106
+
107
+ if results.empty?
108
+ lookup.result = nil
109
+ else
110
+ lookup.result = USEnrichment::Business::Detail::Response.new(results[0])
111
+ end
112
+ lookup.result
113
+ end
114
+
67
115
  def send_generic_lookup(lookup, data_set, data_sub_set = nil)
68
116
  if (lookup.instance_of? String)
69
117
  __send(USEnrichment::Lookup.new(lookup, data_set, data_sub_set))
@@ -74,15 +122,15 @@ module SmartyStreets
74
122
  end
75
123
  end
76
124
 
77
- def __send(lookup)
78
- smarty_request = Request.new
79
-
80
- return if lookup.nil?
125
+ private
81
126
 
82
- if (!lookup.etag.nil?)
83
- smarty_request.header["ETAG"] = lookup.etag
127
+ def __send(lookup)
128
+ if lookup.nil? || (blank?(lookup.smarty_key) && blank?(lookup.street) && blank?(lookup.freeform))
129
+ raise SmartyError.new("Lookup requires one of 'smartykey', 'street', or 'freeform' to be set")
84
130
  end
85
131
 
132
+ smarty_request = Request.new
133
+
86
134
  if (!lookup.features.nil?)
87
135
  add_parameter(smarty_request, 'features', lookup.features)
88
136
  end
@@ -105,43 +153,75 @@ module SmartyStreets
105
153
  smarty_request.url_components = '/' + lookup.smarty_key + '/' + lookup.data_set + '/' + lookup.data_sub_set
106
154
  end
107
155
  end
108
- for key in lookup.custom_param_hash.keys do
109
- add_parameter(smarty_request, key, lookup.custom_param_hash[key])
110
- end
156
+
157
+ apply_common_request_fields(smarty_request, lookup)
111
158
 
112
159
  response = @sender.send(smarty_request)
160
+ capture_response_etag(response, lookup)
113
161
  results = @serializer.deserialize(response.payload)
114
-
162
+
115
163
  results = [] if results.nil?
116
164
  raise response.error if response.error
117
-
165
+
118
166
  output = []
119
167
  results.each do |raw_result|
120
168
  result = nil
121
169
  if lookup.data_sub_set == "principal"
122
- result = USEnrichment::Property::Principal::Response.new(raw_result, response.header['etag'])
170
+ result = USEnrichment::Property::Principal::Response.new(raw_result)
123
171
  end
124
172
  if lookup.data_set == "geo-reference"
125
- result = USEnrichment::GeoReference::Response.new(raw_result, response.header['etag'])
173
+ result = USEnrichment::GeoReference::Response.new(raw_result)
126
174
  end
127
175
  if lookup.data_set == "risk"
128
- result = USEnrichment::Risk::Response.new(raw_result, response.header['etag'])
176
+ result = USEnrichment::Risk::Response.new(raw_result)
129
177
  end
130
178
  if lookup.data_set == "secondary"
131
179
  if lookup.data_sub_set == "count"
132
- result = USEnrichment::Secondary::Count::Response.new(raw_result, response.header['etag'])
180
+ result = USEnrichment::Secondary::Count::Response.new(raw_result)
133
181
  elsif lookup.data_sub_set.nil?
134
- result = USEnrichment::Secondary::Response.new(raw_result, response.header['etag'])
182
+ result = USEnrichment::Secondary::Response.new(raw_result)
135
183
  end
136
184
  end
185
+ if lookup.data_set == "business" && lookup.data_sub_set.nil?
186
+ result = USEnrichment::Business::Summary::Response.new(raw_result)
187
+ end
137
188
  output << result
138
189
  end
139
190
  output
140
191
  end
141
192
 
193
+ def apply_common_request_fields(request, lookup)
194
+ unless lookup.include_array.empty?
195
+ request.parameters['include'] = lookup.include_array.join(',')
196
+ end
197
+ unless lookup.exclude_array.empty?
198
+ request.parameters['exclude'] = lookup.exclude_array.join(',')
199
+ end
200
+ unless lookup.request_etag.nil?
201
+ request.header['Etag'] = lookup.request_etag
202
+ end
203
+ lookup.custom_param_hash.each do |key, value|
204
+ add_parameter(request, key, value)
205
+ end
206
+ end
207
+
208
+ def capture_response_etag(response, lookup)
209
+ return if response.nil?
210
+ etag = response.find_header('etag')
211
+ lookup.response_etag = etag unless etag.nil?
212
+ end
213
+
214
+ def encode_path_segment(value)
215
+ URI.encode_www_form_component(value).gsub('+', '%20')
216
+ end
217
+
142
218
  def add_parameter(request, key, value)
143
219
  request.parameters[key] = value unless value.nil? or value.empty?
144
220
  end
221
+
222
+ def blank?(value)
223
+ value.nil? || value.to_s.strip.empty?
224
+ end
145
225
  end
146
226
  end
147
- end
227
+ end
@@ -4,15 +4,14 @@ module SmartyStreets
4
4
  module USEnrichment
5
5
  module GeoReference
6
6
  class Response
7
- attr_reader :smarty_key, :data_set_name, :data_set_version, :matched_address, :attributes, :etag
7
+ attr_reader :smarty_key, :data_set_name, :data_set_version, :matched_address, :attributes
8
8
 
9
- def initialize(obj, etag=nil)
9
+ def initialize(obj)
10
10
  @smarty_key = obj['smarty_key']
11
11
  @data_set_name = obj['data_set_name']
12
12
  @data_set_version = obj['data_set_version']
13
13
  @matched_address = obj['matched_address']
14
14
  @attributes = Attributes.new(obj['attributes'])
15
- @etag = etag
16
15
  end
17
16
  end
18
17
  end
@@ -1,10 +1,37 @@
1
1
  require_relative '../json_able'
2
+
2
3
  module SmartyStreets
3
4
  module USEnrichment
4
- class Lookup < JSONAble
5
- attr_accessor :smarty_key, :data_set, :data_sub_set, :freeform, :street, :city, :state, :zipcode, :etag, :features, :custom_param_hash
6
-
7
- def initialize(smarty_key=nil, data_set=nil, data_sub_set=nil, freeform=nil, street=nil, city=nil, state=nil, zipcode=nil, etag=nil, features=nil, custom_param_hash=nil)
5
+ class LookupBase < JSONAble
6
+ attr_accessor :request_etag, :response_etag, :include_array, :exclude_array, :features, :custom_param_hash
7
+
8
+ def initialize
9
+ @request_etag = nil
10
+ @response_etag = nil
11
+ @include_array = []
12
+ @exclude_array = []
13
+ @features = nil
14
+ @custom_param_hash = {}
15
+ end
16
+
17
+ def add_custom_parameter(parameter, value)
18
+ @custom_param_hash[parameter] = value
19
+ end
20
+
21
+ def add_include_attribute(attribute)
22
+ @include_array << attribute unless @include_array.include?(attribute)
23
+ end
24
+
25
+ def add_exclude_attribute(attribute)
26
+ @exclude_array << attribute unless @exclude_array.include?(attribute)
27
+ end
28
+ end
29
+
30
+ class Lookup < LookupBase
31
+ attr_accessor :smarty_key, :data_set, :data_sub_set, :freeform, :street, :city, :state, :zipcode
32
+
33
+ def initialize(smarty_key=nil, data_set=nil, data_sub_set=nil, freeform=nil, street=nil, city=nil, state=nil, zipcode=nil, request_etag=nil, features=nil)
34
+ super()
8
35
  @smarty_key = smarty_key
9
36
  @data_set = data_set
10
37
  @data_sub_set = data_sub_set
@@ -13,14 +40,19 @@ module SmartyStreets
13
40
  @city = city
14
41
  @state = state
15
42
  @zipcode = zipcode
16
- @etag = etag
43
+ @request_etag = request_etag
17
44
  @features = features
18
- @custom_param_hash = {}
19
45
  end
46
+ end
20
47
 
21
- def add_custom_parameter(parameter, value)
22
- @custom_param_hash[parameter] = value
48
+ class BusinessDetailLookup < LookupBase
49
+ attr_accessor :business_id, :result
50
+
51
+ def initialize(business_id=nil)
52
+ super()
53
+ @business_id = business_id
54
+ @result = nil
23
55
  end
24
56
  end
25
57
  end
26
- end
58
+ end
@@ -5,15 +5,14 @@ module SmartyStreets
5
5
  module Property
6
6
  module Principal
7
7
  class Response
8
- attr_reader :smarty_key, :data_set_name, :data_subset_name, :matched_address, :attributes, :etag
9
-
10
- def initialize(obj, etag=nil)
8
+ attr_reader :smarty_key, :data_set_name, :data_subset_name, :matched_address, :attributes
9
+
10
+ def initialize(obj)
11
11
  @smarty_key = obj['smarty_key']
12
12
  @data_set_name = obj['data_set_name']
13
13
  @data_subset_name = obj['data_subset_name']
14
14
  @matched_address = obj['matched_address']
15
15
  @attributes = Attributes.new(obj['attributes'])
16
- @etag = etag
17
16
  end
18
17
  end
19
18
  end
@@ -4,14 +4,13 @@ module SmartyStreets
4
4
  module USEnrichment
5
5
  module Risk
6
6
  class Response
7
- attr_reader :smarty_key, :data_set_name, :matched_address, :attributes, :etag
7
+ attr_reader :smarty_key, :data_set_name, :matched_address, :attributes
8
8
 
9
- def initialize(obj, etag=nil)
9
+ def initialize(obj)
10
10
  @smarty_key = obj['smarty_key']
11
11
  @data_set_name = obj['data_set_name']
12
12
  @matched_address = obj['matched_address']
13
13
  @attributes = Attributes.new(obj['attributes'])
14
- @etag = etag
15
14
  end
16
15
  end
17
16
  end
@@ -3,13 +3,12 @@ module SmartyStreets
3
3
  module Secondary
4
4
  module Count
5
5
  class Response
6
- attr_reader :smarty_key, :matched_address, :count, :etag
6
+ attr_reader :smarty_key, :matched_address, :count
7
7
 
8
- def initialize(obj, etag=nil)
8
+ def initialize(obj)
9
9
  @smarty_key = obj['smarty_key']
10
10
  @matched_address = obj['matched_address']
11
11
  @count = obj['count']
12
- @etag = etag
13
12
  end
14
13
  end
15
14
  end
@@ -6,9 +6,9 @@ module SmartyStreets
6
6
  module USEnrichment
7
7
  module Secondary
8
8
  class Response
9
- attr_reader :smarty_key, :matched_address, :root_address, :aliases, :secondaries, :etag
9
+ attr_reader :smarty_key, :matched_address, :root_address, :aliases, :secondaries
10
10
 
11
- def initialize(obj, etag=nil)
11
+ def initialize(obj)
12
12
  @smarty_key = obj['smarty_key']
13
13
  @matched_address = obj['matched_address']
14
14
  @root_address = Secondary::RootAddressEntry.new(obj['root_address'])
@@ -16,7 +16,6 @@ module SmartyStreets
16
16
  @aliases = createAliasesArray(obj['aliases'])
17
17
  end
18
18
  @secondaries = createSecondariesArray(obj['secondaries'])
19
- @etag=etag
20
19
  end
21
20
 
22
21
  def createAliasesArray(obj)
@@ -1,13 +1,14 @@
1
- require_relative './us_enrichment/property/financial/attributes'
2
- require_relative './us_enrichment/property/financial/history_entry'
3
- require_relative './us_enrichment/property/financial/response'
4
-
5
1
  require_relative './us_enrichment/property/principal/attributes'
6
2
  require_relative './us_enrichment/property/principal/response'
7
3
 
4
+ require_relative './us_enrichment/business/summary/business_entry'
5
+ require_relative './us_enrichment/business/summary/response'
6
+ require_relative './us_enrichment/business/detail/attributes'
7
+ require_relative './us_enrichment/business/detail/response'
8
+
8
9
  require_relative './us_enrichment/client'
9
10
 
10
11
  module SmartyStreets
11
12
  module USEnrichment
12
13
  end
13
- end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module SmartyStreets
2
- VERSION = '7.5.0' # DO NOT EDIT (this is updated by a build job when a new release is published)
2
+ VERSION = '8.0.0' # DO NOT EDIT (this is updated by a build job when a new release is published)
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smartystreets_ruby_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.5.0
4
+ version: 8.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SmartyStreets SDK Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-04-01 00:00:00.000000000 Z
11
+ date: 2026-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -97,6 +97,8 @@ files:
97
97
  - examples/international_example.rb
98
98
  - examples/international_postal_code_example.rb
99
99
  - examples/us_autocomplete_pro_example.rb
100
+ - examples/us_enrichment_business_example.rb
101
+ - examples/us_enrichment_etag_example.rb
100
102
  - examples/us_enrichment_example.rb
101
103
  - examples/us_extract_example.rb
102
104
  - examples/us_reverse_geo_example.rb
@@ -153,6 +155,10 @@ files:
153
155
  - lib/smartystreets_ruby_sdk/us_autocomplete_pro/lookup.rb
154
156
  - lib/smartystreets_ruby_sdk/us_autocomplete_pro/suggestion.rb
155
157
  - lib/smartystreets_ruby_sdk/us_enrichment.rb
158
+ - lib/smartystreets_ruby_sdk/us_enrichment/business/detail/attributes.rb
159
+ - lib/smartystreets_ruby_sdk/us_enrichment/business/detail/response.rb
160
+ - lib/smartystreets_ruby_sdk/us_enrichment/business/summary/business_entry.rb
161
+ - lib/smartystreets_ruby_sdk/us_enrichment/business/summary/response.rb
156
162
  - lib/smartystreets_ruby_sdk/us_enrichment/client.rb
157
163
  - lib/smartystreets_ruby_sdk/us_enrichment/geo_reference/attributes.rb
158
164
  - lib/smartystreets_ruby_sdk/us_enrichment/geo_reference/census_block_entry.rb