usps-imis-api 1.0.0.pre.rc.3 → 1.0.0.pre.rc.4
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 +4 -4
- data/Gemfile.lock +1 -1
- data/Readme.md +10 -8
- data/lib/usps/imis/api.rb +35 -141
- data/lib/usps/imis/business_object.rb +131 -0
- data/lib/usps/imis/mapper.rb +1 -1
- data/lib/usps/imis/panel/base_panel.rb +6 -4
- data/lib/usps/imis/requests.rb +31 -0
- data/lib/usps/imis/version.rb +1 -1
- data/lib/usps/imis.rb +2 -0
- data/spec/lib/usps/imis/api_spec.rb +39 -36
- data/spec/lib/usps/imis/business_object_spec.rb +40 -0
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bb187f7e4a8497da991378eec6a9893c5c2a5e637b808a9225ab72ebd5ee385d
|
|
4
|
+
data.tar.gz: 0d09118f25fce28b94ddbc1257e9670fe3454e34df094885bc9cf35cbb1a86a0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f50698bc529a6d66d3c69e201d696cdfde1f24c7bf414ab1f655ebdf3b21e1bd512b8e00476ffa62e3ded1a50d72e82586b8f11c002291c5a8038ad5f4cdd2d6
|
|
7
|
+
data.tar.gz: '09e2849e666c312d0a974efc14b5133ac6e2f0ef181a6715f83ae420b6ba48f6a1566cc749a1dcbce614989c9e5b9fa343ba4dd6a56f1ecd47a9a14b7572617a'
|
data/Gemfile.lock
CHANGED
data/Readme.md
CHANGED
|
@@ -13,7 +13,7 @@ gem install usps-imis-api
|
|
|
13
13
|
or add this line to your Gemfile:
|
|
14
14
|
|
|
15
15
|
```ruby
|
|
16
|
-
gem 'usps-imis-api', '>= 0.
|
|
16
|
+
gem 'usps-imis-api', '>= 0.6.0'
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## Setup
|
|
@@ -82,7 +82,7 @@ To fetch member data, run e.g.:
|
|
|
82
82
|
```ruby
|
|
83
83
|
api.imis_id = 31092
|
|
84
84
|
|
|
85
|
-
data = api.
|
|
85
|
+
data = api.on('ABC_ASC_Individual_Demog').get
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
### PUT Fields
|
|
@@ -93,7 +93,7 @@ To update member data, run e.g.:
|
|
|
93
93
|
api.imis_id = 31092
|
|
94
94
|
|
|
95
95
|
data = { 'MMS_Updated' => Time.now.strftime('%Y-%m-%dT%H:%M:%S'), 'TotMMS' => new_total }
|
|
96
|
-
update = api.
|
|
96
|
+
update = api.on('ABC_ASC_Individual_Demog').put_fields(data)
|
|
97
97
|
```
|
|
98
98
|
|
|
99
99
|
This method fetches the current data structure, and filters it down to just what you want to
|
|
@@ -106,7 +106,7 @@ To update member data, run e.g.:
|
|
|
106
106
|
```ruby
|
|
107
107
|
api.imis_id = 31092
|
|
108
108
|
|
|
109
|
-
update = api.
|
|
109
|
+
update = api.on('ABC_ASC_Individual_Demog').put(complete_imis_object)
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
This method requires a complete iMIS data structure.
|
|
@@ -116,7 +116,7 @@ This method requires a complete iMIS data structure.
|
|
|
116
116
|
To create new member data, run e.g.:
|
|
117
117
|
|
|
118
118
|
```ruby
|
|
119
|
-
created = api.
|
|
119
|
+
created = api.on('ABC_ASC_Individual_Demog').post(complete_imis_object)
|
|
120
120
|
```
|
|
121
121
|
|
|
122
122
|
This method requires a complete iMIS data structure.
|
|
@@ -128,7 +128,7 @@ To remove member data, run e.g.:
|
|
|
128
128
|
```ruby
|
|
129
129
|
api.imis_id = 31092
|
|
130
130
|
|
|
131
|
-
api.
|
|
131
|
+
api.on('ABC_ASC_Individual_Demog').delete
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
This returns a blank string on success.
|
|
@@ -202,9 +202,11 @@ previous value.
|
|
|
202
202
|
|
|
203
203
|
```ruby
|
|
204
204
|
api.with(31092) do
|
|
205
|
-
# These
|
|
205
|
+
# These four requests are identical:
|
|
206
206
|
|
|
207
|
-
|
|
207
|
+
on('ABC_ASC_Individual_Demog') { put('TotMMS' => 15) }
|
|
208
|
+
|
|
209
|
+
on('ABC_ASC_Individual_Demog').put('TotMMS' => 15)
|
|
208
210
|
|
|
209
211
|
mapper.update(mm: 15)
|
|
210
212
|
|
data/lib/usps/imis/api.rb
CHANGED
|
@@ -5,14 +5,12 @@ module Usps
|
|
|
5
5
|
# The core API wrapper
|
|
6
6
|
#
|
|
7
7
|
class Api
|
|
8
|
+
include Requests
|
|
9
|
+
|
|
8
10
|
# Endpoint for (re-)authentication requests
|
|
9
11
|
#
|
|
10
12
|
AUTHENTICATION_PATH = 'Token'
|
|
11
13
|
|
|
12
|
-
# Endpoint for general API requests
|
|
13
|
-
#
|
|
14
|
-
API_PATH = 'api'
|
|
15
|
-
|
|
16
14
|
# Endpoint for IQA query requests
|
|
17
15
|
#
|
|
18
16
|
QUERY_PATH = 'api/Query'
|
|
@@ -52,7 +50,7 @@ module Usps
|
|
|
52
50
|
def imis_id=(id)
|
|
53
51
|
raise Error::ApiError, 'Cannot change iMIS ID while locked' if lock_imis_id
|
|
54
52
|
|
|
55
|
-
@imis_id = id
|
|
53
|
+
@imis_id = id&.to_i&.to_s
|
|
56
54
|
end
|
|
57
55
|
|
|
58
56
|
# Convert a member's certificate number into an iMIS ID number
|
|
@@ -76,6 +74,8 @@ module Usps
|
|
|
76
74
|
#
|
|
77
75
|
# While in this block, changes to the value of +imis_id+ are not allowed
|
|
78
76
|
#
|
|
77
|
+
# If no block is given, this sets the iMIS ID and returns self.
|
|
78
|
+
#
|
|
79
79
|
# @param id [Integer, String] iMIS ID to select for requests within the block
|
|
80
80
|
#
|
|
81
81
|
# @example
|
|
@@ -86,107 +86,68 @@ module Usps
|
|
|
86
86
|
def with(id, &)
|
|
87
87
|
old_id = imis_id
|
|
88
88
|
self.imis_id = id
|
|
89
|
+
return self unless block_given?
|
|
89
90
|
|
|
90
91
|
@lock_imis_id = true
|
|
91
92
|
instance_eval(&)
|
|
92
93
|
ensure
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
if block_given?
|
|
95
|
+
@lock_imis_id = false
|
|
96
|
+
self.imis_id = old_id
|
|
97
|
+
end
|
|
95
98
|
end
|
|
96
99
|
|
|
97
|
-
#
|
|
100
|
+
# Run an IQA Query
|
|
98
101
|
#
|
|
99
|
-
# @param
|
|
100
|
-
# @
|
|
102
|
+
# @param query_name [String] Full path of the query in IQA, e.g. +$/_ABC/Fiander/iMIS_ID+
|
|
103
|
+
# @query_params [Hash] Conforms to pattern +{ param_name => param_value }+
|
|
101
104
|
#
|
|
102
105
|
# @return [Hash] Response data from the API
|
|
103
106
|
#
|
|
104
|
-
def
|
|
105
|
-
|
|
107
|
+
def query(query_name, query_params = {})
|
|
108
|
+
query_params[:QueryName] = query_name
|
|
109
|
+
path = "#{QUERY_PATH}?#{query_params.to_query}"
|
|
110
|
+
uri = URI(File.join(Imis.configuration.hostname, path))
|
|
106
111
|
request = Net::HTTP::Get.new(uri)
|
|
107
112
|
result = submit(uri, authorize(request))
|
|
108
113
|
JSON.parse(result.body)
|
|
109
114
|
end
|
|
110
115
|
|
|
111
|
-
#
|
|
116
|
+
# An instance of +BusinessObject+, using this instance as its parent +Api+
|
|
112
117
|
#
|
|
113
118
|
# @param business_object_name [String] Name of the business object
|
|
114
|
-
# @param fields [Hash] Conforms to pattern +{ field_key => value }+
|
|
115
119
|
# @param url_id [String] Override the ID param of the URL (e.g. used for Panels)
|
|
116
120
|
#
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def put_fields(business_object_name, fields, url_id: nil)
|
|
120
|
-
updated = filter_fields(business_object_name, fields)
|
|
121
|
-
put(business_object_name, updated, url_id:)
|
|
121
|
+
def business_object(business_object_name, url_id: nil)
|
|
122
|
+
BusinessObject.new(self, business_object_name, url_id:)
|
|
122
123
|
end
|
|
123
124
|
|
|
124
|
-
#
|
|
125
|
-
#
|
|
126
|
-
# @param business_object_name [String] Name of the business object
|
|
127
|
-
# @param body [Hash] Full raw API object data
|
|
128
|
-
# @param url_id [String] Override the ID param of the URL (e.g. used for Panels)
|
|
125
|
+
# Run requests as DSL, with specific +BusinessObject+ only maintained for this scope
|
|
129
126
|
#
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
def put(business_object_name, body, url_id: nil)
|
|
133
|
-
uri = uri_for(business_object_name, url_id:)
|
|
134
|
-
request = Net::HTTP::Put.new(uri)
|
|
135
|
-
request.body = JSON.dump(body)
|
|
136
|
-
result = submit(uri, authorize(request))
|
|
137
|
-
JSON.parse(result.body)
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# Create a business object for the current member
|
|
127
|
+
# If no block is given, this returns the specified +BusinessObject+.
|
|
141
128
|
#
|
|
142
129
|
# @param business_object_name [String] Name of the business object
|
|
143
|
-
# @param body [Hash] Full raw API object data
|
|
144
130
|
# @param url_id [String] Override the ID param of the URL (e.g. used for Panels)
|
|
145
131
|
#
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
uri = uri_for(business_object_name, url_id:)
|
|
150
|
-
request = Net::HTTP::Post.new(uri)
|
|
151
|
-
request.body = JSON.dump(body)
|
|
152
|
-
result = submit(uri, authorize(request))
|
|
153
|
-
JSON.parse(result.body)
|
|
154
|
-
end
|
|
132
|
+
def on(business_object_name, url_id: nil, &)
|
|
133
|
+
object = business_object(business_object_name, url_id:)
|
|
134
|
+
return object unless block_given?
|
|
155
135
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
# @param url_id [String] Override the ID param of the URL (e.g. used for Panels)
|
|
160
|
-
#
|
|
161
|
-
# @return [String] Error response body from the API, or empty string on success
|
|
162
|
-
#
|
|
163
|
-
def delete(business_object_name, url_id: nil)
|
|
164
|
-
uri = uri_for(business_object_name, url_id:)
|
|
165
|
-
request = Net::HTTP::Delete.new(uri)
|
|
166
|
-
result = submit(uri, authorize(request))
|
|
167
|
-
result.body
|
|
136
|
+
result = nil
|
|
137
|
+
object.tap { |obj| result = obj.instance_eval(&) }
|
|
138
|
+
result
|
|
168
139
|
end
|
|
169
140
|
|
|
170
|
-
#
|
|
171
|
-
#
|
|
172
|
-
# @param query_name [String] Full path of the query in IQA, e.g. +$/_ABC/Fiander/iMIS_ID+
|
|
173
|
-
# @query_params [Hash] Conforms to pattern +{ param_name => param_value }+
|
|
141
|
+
# An instance of +Mapper+, using this instance as its parent +Api+
|
|
174
142
|
#
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
def query(query_name, query_params = {})
|
|
178
|
-
query_params[:QueryName] = query_name
|
|
179
|
-
path = "#{QUERY_PATH}?#{query_params.to_query}"
|
|
180
|
-
uri = URI(File.join(imis_hostname, path))
|
|
181
|
-
request = Net::HTTP::Get.new(uri)
|
|
182
|
-
result = submit(uri, authorize(request))
|
|
183
|
-
JSON.parse(result.body)
|
|
143
|
+
def mapper
|
|
144
|
+
@mapper ||= Mapper.new(self)
|
|
184
145
|
end
|
|
185
146
|
|
|
186
|
-
#
|
|
147
|
+
# Convenience alias for updating mapped fields
|
|
187
148
|
#
|
|
188
|
-
def
|
|
189
|
-
|
|
149
|
+
def update(data)
|
|
150
|
+
mapper.update(data)
|
|
190
151
|
end
|
|
191
152
|
|
|
192
153
|
# Convenience accessor for available Panel objects, each using this instance as its parent
|
|
@@ -199,56 +160,16 @@ module Usps
|
|
|
199
160
|
)
|
|
200
161
|
end
|
|
201
162
|
|
|
202
|
-
# Convenience alias for updating mapped fields
|
|
203
|
-
#
|
|
204
|
-
def update(data)
|
|
205
|
-
mapper.update(data)
|
|
206
|
-
end
|
|
207
|
-
|
|
208
163
|
# Ruby 3.5 instance variable filter
|
|
209
164
|
#
|
|
210
165
|
def instance_variables_to_inspect = %i[@token_expiration @imis_id]
|
|
211
166
|
|
|
212
167
|
private
|
|
213
168
|
|
|
214
|
-
def client(uri)
|
|
215
|
-
Net::HTTP.new(uri.host, uri.port).tap do |http|
|
|
216
|
-
http.use_ssl = true
|
|
217
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
218
|
-
end
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
def imis_hostname
|
|
222
|
-
Imis.configuration.hostname
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
# Authorize a request prior to submitting
|
|
226
|
-
#
|
|
227
|
-
# If the current token is missing/expired, request a new one
|
|
228
|
-
#
|
|
229
|
-
def authorize(request)
|
|
230
|
-
authenticate if token_expiration < Time.now
|
|
231
|
-
request.tap { |r| r.add_field('Authorization', "Bearer #{token}") }
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
# Construct a business object API endpoint address
|
|
235
|
-
#
|
|
236
|
-
def uri_for(business_object_name, url_id: nil)
|
|
237
|
-
url_id ||= imis_id
|
|
238
|
-
url_id = CGI.escape(url_id)
|
|
239
|
-
URI(File.join(imis_hostname, "#{API_PATH}/#{business_object_name}/#{url_id}"))
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
def submit(uri, request)
|
|
243
|
-
client(uri).request(request).tap do |result|
|
|
244
|
-
raise Error::ResponseError.from(result) unless result.is_a?(Net::HTTPSuccess)
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
|
-
|
|
248
169
|
# Authenticate to the iMIS API, and store the access token and expiration time
|
|
249
170
|
#
|
|
250
171
|
def authenticate
|
|
251
|
-
uri = URI(File.join(
|
|
172
|
+
uri = URI(File.join(Imis.configuration.hostname, AUTHENTICATION_PATH))
|
|
252
173
|
req = Net::HTTP::Post.new(uri)
|
|
253
174
|
authentication_data = {
|
|
254
175
|
grant_type: 'password',
|
|
@@ -262,33 +183,6 @@ module Usps
|
|
|
262
183
|
@token = json['access_token']
|
|
263
184
|
@token_expiration = Time.parse(json['.expires'])
|
|
264
185
|
end
|
|
265
|
-
|
|
266
|
-
# Manually assemble the matching data structure, with fields in the correct order
|
|
267
|
-
#
|
|
268
|
-
def filter_fields(business_object_name, fields)
|
|
269
|
-
existing = get(business_object_name)
|
|
270
|
-
|
|
271
|
-
JSON.parse(JSON.dump(existing)).tap do |updated|
|
|
272
|
-
# The first property is always the iMIS ID again
|
|
273
|
-
updated['Properties']['$values'] = [existing['Properties']['$values'][0]]
|
|
274
|
-
|
|
275
|
-
# Iterate through all existing fields
|
|
276
|
-
existing['Properties']['$values'].each do |value|
|
|
277
|
-
next unless fields.keys.include?(value['Name'])
|
|
278
|
-
|
|
279
|
-
# Strings are not wrapped in the type definition structure
|
|
280
|
-
new_value = fields[value['Name']]
|
|
281
|
-
if new_value.is_a?(String)
|
|
282
|
-
value['Value'] = new_value
|
|
283
|
-
else
|
|
284
|
-
value['Value']['$value'] = new_value
|
|
285
|
-
end
|
|
286
|
-
|
|
287
|
-
# Add the completed field with the updated value
|
|
288
|
-
updated['Properties']['$values'] << value
|
|
289
|
-
end
|
|
290
|
-
end
|
|
291
|
-
end
|
|
292
186
|
end
|
|
293
187
|
end
|
|
294
188
|
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
# DEV
|
|
6
|
+
class BusinessObject
|
|
7
|
+
include Requests
|
|
8
|
+
|
|
9
|
+
# Endpoint for general API requests
|
|
10
|
+
#
|
|
11
|
+
API_PATH = 'api'
|
|
12
|
+
|
|
13
|
+
# The parent +Api+ object
|
|
14
|
+
#
|
|
15
|
+
attr_reader :api
|
|
16
|
+
|
|
17
|
+
# Name of the iMIS Business Object
|
|
18
|
+
#
|
|
19
|
+
attr_reader :business_object_name
|
|
20
|
+
|
|
21
|
+
# Override ID param of the URL (e.g. used for Panels)
|
|
22
|
+
#
|
|
23
|
+
attr_reader :url_id
|
|
24
|
+
|
|
25
|
+
# A new instance of +BusinessObject+
|
|
26
|
+
#
|
|
27
|
+
def initialize(api, business_object_name, url_id: nil)
|
|
28
|
+
@api = api
|
|
29
|
+
@business_object_name = business_object_name
|
|
30
|
+
@url_id = url_id
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Get a business object for the current member
|
|
34
|
+
#
|
|
35
|
+
# @return [Hash] Response data from the API
|
|
36
|
+
#
|
|
37
|
+
def get
|
|
38
|
+
request = Net::HTTP::Get.new(uri)
|
|
39
|
+
result = submit(uri, authorize(request))
|
|
40
|
+
JSON.parse(result.body)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Update only specific fields on a business object for the current member
|
|
44
|
+
#
|
|
45
|
+
# @param fields [Hash] Conforms to pattern +{ field_key => value }+
|
|
46
|
+
#
|
|
47
|
+
# @return [Hash] Response data from the API
|
|
48
|
+
#
|
|
49
|
+
def put_fields(fields)
|
|
50
|
+
updated = filter_fields(fields)
|
|
51
|
+
put(updated)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Update a business object for the current member
|
|
55
|
+
#
|
|
56
|
+
# @param body [Hash] Full raw API object data
|
|
57
|
+
#
|
|
58
|
+
# @return [Hash] Response data from the API
|
|
59
|
+
#
|
|
60
|
+
def put(body)
|
|
61
|
+
request = Net::HTTP::Put.new(uri)
|
|
62
|
+
request.body = JSON.dump(body)
|
|
63
|
+
result = submit(uri, authorize(request))
|
|
64
|
+
JSON.parse(result.body)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Create a business object for the current member
|
|
68
|
+
#
|
|
69
|
+
# @param body [Hash] Full raw API object data
|
|
70
|
+
#
|
|
71
|
+
# @return [Hash] Response data from the API
|
|
72
|
+
#
|
|
73
|
+
def post(body)
|
|
74
|
+
request = Net::HTTP::Post.new(uri)
|
|
75
|
+
request.body = JSON.dump(body)
|
|
76
|
+
result = submit(uri, authorize(request))
|
|
77
|
+
JSON.parse(result.body)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Remove a business object for the current member
|
|
81
|
+
#
|
|
82
|
+
# @return [String] Error response body from the API, or empty string on success
|
|
83
|
+
#
|
|
84
|
+
def delete
|
|
85
|
+
request = Net::HTTP::Delete.new(uri)
|
|
86
|
+
result = submit(uri, authorize(request))
|
|
87
|
+
result.body
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
|
|
92
|
+
def token = api.token
|
|
93
|
+
def token_expiration = api.token_expiration
|
|
94
|
+
|
|
95
|
+
# Construct a business object API endpoint address
|
|
96
|
+
#
|
|
97
|
+
def uri
|
|
98
|
+
id_for_url = url_id ? CGI.escape(url_id) : api.imis_id
|
|
99
|
+
full_path = "#{API_PATH}/#{business_object_name}/#{id_for_url}"
|
|
100
|
+
URI(File.join(Imis.configuration.hostname, full_path))
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Manually assemble the matching data structure, with fields in the correct order
|
|
104
|
+
#
|
|
105
|
+
def filter_fields(fields)
|
|
106
|
+
existing = get
|
|
107
|
+
|
|
108
|
+
JSON.parse(JSON.dump(existing)).tap do |updated|
|
|
109
|
+
# The first property is always the iMIS ID again
|
|
110
|
+
updated['Properties']['$values'] = [existing['Properties']['$values'][0]]
|
|
111
|
+
|
|
112
|
+
# Iterate through all existing fields
|
|
113
|
+
existing['Properties']['$values'].each do |value|
|
|
114
|
+
next unless fields.keys.include?(value['Name'])
|
|
115
|
+
|
|
116
|
+
# Strings are not wrapped in the type definition structure
|
|
117
|
+
new_value = fields[value['Name']]
|
|
118
|
+
if new_value.is_a?(String)
|
|
119
|
+
value['Value'] = new_value
|
|
120
|
+
else
|
|
121
|
+
value['Value']['$value'] = new_value
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Add the completed field with the updated value
|
|
125
|
+
updated['Properties']['$values'] << value
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
data/lib/usps/imis/mapper.rb
CHANGED
|
@@ -20,7 +20,7 @@ module Usps
|
|
|
20
20
|
# @param ordinal [Integer] The ordinal identifier for the desired object
|
|
21
21
|
#
|
|
22
22
|
def get(ordinal)
|
|
23
|
-
api.
|
|
23
|
+
api.business_object(business_object, url_id: "~#{api.imis_id}|#{ordinal}").get
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
# Create a new object in the Panel
|
|
@@ -28,7 +28,7 @@ module Usps
|
|
|
28
28
|
# @param data [Hash] The record data for the desired object
|
|
29
29
|
#
|
|
30
30
|
def create(data)
|
|
31
|
-
api.
|
|
31
|
+
api.business_object(business_object, url_id: '').post(payload(data))
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
# Update an existing object in the Panel
|
|
@@ -37,7 +37,9 @@ module Usps
|
|
|
37
37
|
# +ordinal+ identifier
|
|
38
38
|
#
|
|
39
39
|
def update(data)
|
|
40
|
-
api
|
|
40
|
+
api
|
|
41
|
+
.business_object(business_object, url_id: "~#{api.imis_id}|#{data[:ordinal]}")
|
|
42
|
+
.put(payload(data))
|
|
41
43
|
end
|
|
42
44
|
|
|
43
45
|
# Remove a specific object from the Panel
|
|
@@ -45,7 +47,7 @@ module Usps
|
|
|
45
47
|
# @param ordinal [Integer] The ordinal identifier for the desired object
|
|
46
48
|
#
|
|
47
49
|
def destroy(ordinal)
|
|
48
|
-
api.
|
|
50
|
+
api.business_object(business_object, url_id: "~#{api.imis_id}|#{ordinal}").delete
|
|
49
51
|
end
|
|
50
52
|
|
|
51
53
|
private
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
module Requests
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def client(uri)
|
|
9
|
+
Net::HTTP.new(uri.host, uri.port).tap do |http|
|
|
10
|
+
http.use_ssl = true
|
|
11
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Authorize a request prior to submitting
|
|
16
|
+
#
|
|
17
|
+
# If the current token is missing/expired, request a new one
|
|
18
|
+
#
|
|
19
|
+
def authorize(request)
|
|
20
|
+
authenticate if token_expiration < Time.now
|
|
21
|
+
request.tap { |r| r.add_field('Authorization', "Bearer #{token}") }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def submit(uri, request)
|
|
25
|
+
client(uri).request(request).tap do |result|
|
|
26
|
+
raise Error::ResponseError.from(result) unless result.is_a?(Net::HTTPSuccess)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/usps/imis/version.rb
CHANGED
data/lib/usps/imis.rb
CHANGED
|
@@ -16,6 +16,8 @@ require_relative 'imis/config'
|
|
|
16
16
|
require_relative 'imis/error/api_error'
|
|
17
17
|
require_relative 'imis/error/mapper_error'
|
|
18
18
|
require_relative 'imis/error/response_error'
|
|
19
|
+
require_relative 'imis/requests'
|
|
20
|
+
require_relative 'imis/business_object'
|
|
19
21
|
require_relative 'imis/api'
|
|
20
22
|
require_relative 'imis/mapper'
|
|
21
23
|
require_relative 'imis/panel/base_panel'
|
|
@@ -41,7 +41,9 @@ describe Usps::Imis::Api do
|
|
|
41
41
|
before { api.imis_id = 31092 }
|
|
42
42
|
|
|
43
43
|
it 'sends an update' do
|
|
44
|
-
expect(api.
|
|
44
|
+
expect(api.business_object('ABC_ASC_Individual_Demog').put_fields('TotMMS' => 15)).to(
|
|
45
|
+
be_a(Hash)
|
|
46
|
+
)
|
|
45
47
|
end
|
|
46
48
|
|
|
47
49
|
context 'when receiving a response error' do
|
|
@@ -61,8 +63,8 @@ describe Usps::Imis::Api do
|
|
|
61
63
|
end
|
|
62
64
|
|
|
63
65
|
it 'wraps the error' do
|
|
64
|
-
expect { api.
|
|
65
|
-
Usps::Imis::Error::ApiError, warning_text
|
|
66
|
+
expect { api.business_object('ABC_ASC_Individual_Demog').put_fields('TotMMS' => 15) }.to(
|
|
67
|
+
raise_error(Usps::Imis::Error::ApiError, warning_text)
|
|
66
68
|
)
|
|
67
69
|
end
|
|
68
70
|
end
|
|
@@ -71,7 +73,7 @@ describe Usps::Imis::Api do
|
|
|
71
73
|
describe '#with' do
|
|
72
74
|
it 'sends an update from put' do
|
|
73
75
|
expect(
|
|
74
|
-
api.with(31092) {
|
|
76
|
+
api.with(31092) { business_object('ABC_ASC_Individual_Demog').put_fields('TotMMS' => 15) }
|
|
75
77
|
).to be_a(Hash)
|
|
76
78
|
end
|
|
77
79
|
|
|
@@ -96,6 +98,39 @@ describe Usps::Imis::Api do
|
|
|
96
98
|
end
|
|
97
99
|
end
|
|
98
100
|
|
|
101
|
+
describe '#on' do
|
|
102
|
+
it 'returns a BusinessObject without a block' do
|
|
103
|
+
expect(api.on('ABC_ASC_Individual_Demog')).to be_a(Usps::Imis::BusinessObject)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'sends an update from put', :aggregate_failures do
|
|
107
|
+
result = api.with(31092) do
|
|
108
|
+
on('ABC_ASC_Individual_Demog') { put_fields({ 'TotMMS' => 15 }) }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
expect(result).to be_a(Hash)
|
|
112
|
+
expect(api.imis_id).to be_nil
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'chains .with().on() to a single block', :aggregate_failures do
|
|
116
|
+
result = api.with(31092).on('ABC_ASC_Individual_Demog') do
|
|
117
|
+
put_fields({ 'TotMMS' => 15 })
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
expect(result).to be_a(Hash)
|
|
121
|
+
expect(api.imis_id).to eq('31092')
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it 'nests on and with', :aggregate_failures do
|
|
125
|
+
result = api.on('ABC_ASC_Individual_Demog') do |object|
|
|
126
|
+
api.with(31092) { object.put_fields({ 'TotMMS' => 15 }) }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
expect(result).to be_a(Hash)
|
|
130
|
+
expect(api.imis_id).to be_nil
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
99
134
|
describe '#inspect' do
|
|
100
135
|
it 'is configured to exclude the token instance variable' do
|
|
101
136
|
expect(api.instance_variables_to_inspect).not_to include(:@token)
|
|
@@ -120,36 +155,4 @@ describe Usps::Imis::Api do
|
|
|
120
155
|
expect(api).to have_received(:authenticate)
|
|
121
156
|
end
|
|
122
157
|
end
|
|
123
|
-
|
|
124
|
-
describe '#filter_fields' do
|
|
125
|
-
let(:expected) do
|
|
126
|
-
{
|
|
127
|
-
'Properties' => {
|
|
128
|
-
'$values' => [
|
|
129
|
-
{ 'Name' => 'Stub iMIS ID', 'Value' => { '$value' => '31092' } },
|
|
130
|
-
{ 'Name' => 'Stub Integer', 'Value' => { '$value' => 43 } },
|
|
131
|
-
{ 'Name' => 'Stub String', 'Value' => 'other' }
|
|
132
|
-
]
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
before do
|
|
138
|
-
allow(api).to receive(:get).and_return({
|
|
139
|
-
'Properties' => {
|
|
140
|
-
'$values' => [
|
|
141
|
-
{ 'Name' => 'Stub iMIS ID', 'Value' => { '$value' => '31092' } },
|
|
142
|
-
{ 'Name' => 'Stub Integer', 'Value' => { '$value' => 42 } },
|
|
143
|
-
{ 'Name' => 'Stub String', 'Value' => 'something' }
|
|
144
|
-
]
|
|
145
|
-
}
|
|
146
|
-
})
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
it 'formats fields correctly' do
|
|
150
|
-
updated = api.send(:filter_fields, 'Stub', { 'Stub Integer' => 43, 'Stub String' => 'other' })
|
|
151
|
-
|
|
152
|
-
expect(updated).to eq(expected)
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
158
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe Usps::Imis::BusinessObject do
|
|
6
|
+
let(:business_object) { described_class.new(api, 'Stub') }
|
|
7
|
+
let(:api) { Usps::Imis::Api.new }
|
|
8
|
+
|
|
9
|
+
describe '#filter_fields' do
|
|
10
|
+
let(:expected) do
|
|
11
|
+
{
|
|
12
|
+
'Properties' => {
|
|
13
|
+
'$values' => [
|
|
14
|
+
{ 'Name' => 'Stub iMIS ID', 'Value' => { '$value' => '31092' } },
|
|
15
|
+
{ 'Name' => 'Stub Integer', 'Value' => { '$value' => 43 } },
|
|
16
|
+
{ 'Name' => 'Stub String', 'Value' => 'other' }
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
before do
|
|
23
|
+
allow(business_object).to receive(:get).and_return({
|
|
24
|
+
'Properties' => {
|
|
25
|
+
'$values' => [
|
|
26
|
+
{ 'Name' => 'Stub iMIS ID', 'Value' => { '$value' => '31092' } },
|
|
27
|
+
{ 'Name' => 'Stub Integer', 'Value' => { '$value' => 42 } },
|
|
28
|
+
{ 'Name' => 'Stub String', 'Value' => 'something' }
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'formats fields correctly' do
|
|
35
|
+
updated = business_object.send(:filter_fields, 'Stub Integer' => 43, 'Stub String' => 'other')
|
|
36
|
+
|
|
37
|
+
expect(updated).to eq(expected)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: usps-imis-api
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.0.pre.rc.
|
|
4
|
+
version: 1.0.0.pre.rc.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Julian Fiander
|
|
@@ -30,6 +30,7 @@ files:
|
|
|
30
30
|
- lib/ext/hash.rb
|
|
31
31
|
- lib/usps/imis.rb
|
|
32
32
|
- lib/usps/imis/api.rb
|
|
33
|
+
- lib/usps/imis/business_object.rb
|
|
33
34
|
- lib/usps/imis/config.rb
|
|
34
35
|
- lib/usps/imis/error/api_error.rb
|
|
35
36
|
- lib/usps/imis/error/mapper_error.rb
|
|
@@ -38,8 +39,10 @@ files:
|
|
|
38
39
|
- lib/usps/imis/panel/base_panel.rb
|
|
39
40
|
- lib/usps/imis/panel/education.rb
|
|
40
41
|
- lib/usps/imis/panel/vsc.rb
|
|
42
|
+
- lib/usps/imis/requests.rb
|
|
41
43
|
- lib/usps/imis/version.rb
|
|
42
44
|
- spec/lib/usps/imis/api_spec.rb
|
|
45
|
+
- spec/lib/usps/imis/business_object_spec.rb
|
|
43
46
|
- spec/lib/usps/imis/config_spec.rb
|
|
44
47
|
- spec/lib/usps/imis/error/api_error_spec.rb
|
|
45
48
|
- spec/lib/usps/imis/error/response_error_spec.rb
|