usps-imis-api 0.6.16 → 0.7.1
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/.rubocop.yml +1 -3
- data/Gemfile.lock +36 -30
- data/Readme.md +39 -15
- data/lib/usps/imis/api.rb +8 -7
- data/lib/usps/imis/business_object.rb +55 -34
- data/lib/usps/imis/config.rb +1 -1
- data/lib/usps/imis/error.rb +51 -0
- data/lib/usps/imis/errors/api_error.rb +11 -0
- data/lib/usps/imis/errors/config_error.rb +11 -0
- data/lib/usps/imis/errors/locked_id_error.rb +15 -0
- data/lib/usps/imis/errors/mapper_error.rb +29 -0
- data/lib/usps/imis/errors/not_found_error.rb +11 -0
- data/lib/usps/imis/errors/panel_unimplemented_error.rb +34 -0
- data/lib/usps/imis/{error → errors}/response_error.rb +4 -7
- data/lib/usps/imis/errors/unexpected_property_type_error.rb +31 -0
- data/lib/usps/imis/mapper.rb +1 -5
- data/lib/usps/imis/mocks/business_object.rb +37 -0
- data/lib/usps/imis/mocks.rb +11 -0
- data/lib/usps/imis/{panel → panels}/base_panel.rb +26 -22
- data/lib/usps/imis/{panel → panels}/education.rb +1 -1
- data/lib/usps/imis/{panel → panels}/vsc.rb +1 -1
- data/lib/usps/imis/panels.rb +25 -0
- data/lib/usps/imis/properties.rb +1 -1
- data/lib/usps/imis/requests.rb +1 -1
- data/lib/usps/imis/version.rb +1 -1
- data/lib/usps/imis.rb +5 -15
- data/spec/lib/usps/imis/api_spec.rb +5 -5
- data/spec/lib/usps/imis/business_object_spec.rb +35 -13
- data/spec/lib/usps/imis/config_spec.rb +1 -1
- data/spec/lib/usps/imis/{error/api_error_spec.rb → error_spec.rb} +1 -1
- data/spec/lib/usps/imis/{error → errors}/response_error_spec.rb +4 -4
- data/spec/lib/usps/imis/mapper_spec.rb +2 -2
- data/spec/lib/usps/imis/{business_object_mock_spec.rb → mocks/business_object_spec.rb} +1 -1
- data/spec/lib/usps/imis/panels/base_panel_spec.rb +33 -0
- data/spec/lib/usps/imis/{panel → panels}/education_spec.rb +12 -2
- data/spec/lib/usps/imis/{panel → panels}/vsc_spec.rb +2 -2
- data/spec/lib/usps/imis/properties_spec.rb +1 -1
- data/usps-imis-api.gemspec +1 -1
- metadata +23 -16
- data/lib/ext/hash.rb +0 -10
- data/lib/usps/imis/business_object_mock.rb +0 -35
- data/lib/usps/imis/error/api_error.rb +0 -44
- data/lib/usps/imis/error/mapper_error.rb +0 -11
- data/spec/lib/usps/imis/panel/base_panel_spec.rb +0 -32
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ca358fc80eed74b0335f6137f71e503fffbc84d6c396c8e1c23c90501eab5b36
|
|
4
|
+
data.tar.gz: 239111a5dfd7cb186fe358fc0227e3063744225cf619e12a91e994f639142e56
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2f31860395762aeead9f002f96867111758a8474ada928ba1369e3122b767f0b27052ed41157d8eac008fade27bdb779389cd65c74ad7cadbb87129ee9c238ff
|
|
7
|
+
data.tar.gz: 7c0f5eaae8592a93192e08ca4cf88e604629de246b8e2f9272880d19e39a218d01a027387720a6c289b7f4490bc6617b57c637ab00201868ecd36fd178748031
|
data/.rubocop.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
plugins:
|
|
2
2
|
- rubocop-rspec
|
|
3
3
|
|
|
4
4
|
AllCops:
|
|
@@ -37,8 +37,6 @@ Lint/UnusedMethodArgument:
|
|
|
37
37
|
Enabled: true
|
|
38
38
|
Lint/UselessAssignment:
|
|
39
39
|
Enabled: true
|
|
40
|
-
Lint/ItWithoutArgumentsInBlock:
|
|
41
|
-
Enabled: false
|
|
42
40
|
|
|
43
41
|
Metrics/MethodLength:
|
|
44
42
|
Enabled: true
|
data/Gemfile.lock
CHANGED
|
@@ -1,37 +1,36 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
usps-imis-api (0.
|
|
4
|
+
usps-imis-api (0.7.1)
|
|
5
5
|
activesupport (~> 8.0)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
|
-
activesupport (8.0
|
|
10
|
+
activesupport (8.1.0)
|
|
11
11
|
base64
|
|
12
|
-
benchmark (>= 0.3)
|
|
13
12
|
bigdecimal
|
|
14
13
|
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
15
14
|
connection_pool (>= 2.2.5)
|
|
16
15
|
drb
|
|
17
16
|
i18n (>= 1.6, < 2)
|
|
17
|
+
json
|
|
18
18
|
logger (>= 1.4.2)
|
|
19
19
|
minitest (>= 5.1)
|
|
20
20
|
securerandom (>= 0.3)
|
|
21
21
|
tzinfo (~> 2.0, >= 2.0.5)
|
|
22
22
|
uri (>= 0.13.1)
|
|
23
|
-
ast (2.4.
|
|
23
|
+
ast (2.4.3)
|
|
24
24
|
base64 (0.3.0)
|
|
25
|
-
benchmark (0.4.1)
|
|
26
25
|
bigdecimal (3.3.1)
|
|
27
26
|
concurrent-ruby (1.3.5)
|
|
28
27
|
connection_pool (2.5.4)
|
|
29
28
|
date (3.4.1)
|
|
30
|
-
diff-lcs (1.
|
|
29
|
+
diff-lcs (1.6.2)
|
|
31
30
|
docile (1.4.1)
|
|
32
|
-
dotenv (3.1.
|
|
31
|
+
dotenv (3.1.8)
|
|
33
32
|
drb (2.2.3)
|
|
34
|
-
erb (5.
|
|
33
|
+
erb (5.1.1)
|
|
35
34
|
i18n (1.14.7)
|
|
36
35
|
concurrent-ruby (~> 1.0)
|
|
37
36
|
io-console (0.8.1)
|
|
@@ -39,70 +38,77 @@ GEM
|
|
|
39
38
|
pp (>= 0.6.0)
|
|
40
39
|
rdoc (>= 4.0.0)
|
|
41
40
|
reline (>= 0.4.2)
|
|
42
|
-
json (2.
|
|
43
|
-
language_server-protocol (3.17.0.
|
|
41
|
+
json (2.15.1)
|
|
42
|
+
language_server-protocol (3.17.0.5)
|
|
43
|
+
lint_roller (1.1.0)
|
|
44
44
|
logger (1.7.0)
|
|
45
45
|
minitest (5.26.0)
|
|
46
|
-
parallel (1.
|
|
47
|
-
parser (3.3.
|
|
46
|
+
parallel (1.27.0)
|
|
47
|
+
parser (3.3.9.0)
|
|
48
48
|
ast (~> 2.4.1)
|
|
49
49
|
racc
|
|
50
50
|
pp (0.6.3)
|
|
51
51
|
prettyprint
|
|
52
52
|
prettyprint (0.2.0)
|
|
53
|
+
prism (1.6.0)
|
|
53
54
|
psych (5.2.6)
|
|
54
55
|
date
|
|
55
56
|
stringio
|
|
56
57
|
racc (1.8.1)
|
|
57
58
|
rainbow (3.1.1)
|
|
58
|
-
rake (13.
|
|
59
|
+
rake (13.3.0)
|
|
59
60
|
rdoc (6.15.0)
|
|
60
61
|
erb
|
|
61
62
|
psych (>= 4.0.0)
|
|
62
63
|
tsort
|
|
63
|
-
regexp_parser (2.
|
|
64
|
+
regexp_parser (2.11.3)
|
|
64
65
|
reline (0.6.2)
|
|
65
66
|
io-console (~> 0.5)
|
|
66
|
-
rspec (3.13.
|
|
67
|
+
rspec (3.13.2)
|
|
67
68
|
rspec-core (~> 3.13.0)
|
|
68
69
|
rspec-expectations (~> 3.13.0)
|
|
69
70
|
rspec-mocks (~> 3.13.0)
|
|
70
|
-
rspec-core (3.13.
|
|
71
|
+
rspec-core (3.13.6)
|
|
71
72
|
rspec-support (~> 3.13.0)
|
|
72
|
-
rspec-expectations (3.13.
|
|
73
|
+
rspec-expectations (3.13.5)
|
|
73
74
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
74
75
|
rspec-support (~> 3.13.0)
|
|
75
|
-
rspec-mocks (3.13.
|
|
76
|
+
rspec-mocks (3.13.6)
|
|
76
77
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
77
78
|
rspec-support (~> 3.13.0)
|
|
78
|
-
rspec-support (3.13.
|
|
79
|
-
rubocop (1.
|
|
79
|
+
rspec-support (3.13.6)
|
|
80
|
+
rubocop (1.81.6)
|
|
80
81
|
json (~> 2.3)
|
|
81
|
-
language_server-protocol (
|
|
82
|
+
language_server-protocol (~> 3.17.0.2)
|
|
83
|
+
lint_roller (~> 1.1.0)
|
|
82
84
|
parallel (~> 1.10)
|
|
83
85
|
parser (>= 3.3.0.2)
|
|
84
86
|
rainbow (>= 2.2.2, < 4.0)
|
|
85
|
-
regexp_parser (>= 2.
|
|
86
|
-
rubocop-ast (>= 1.
|
|
87
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
88
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
87
89
|
ruby-progressbar (~> 1.7)
|
|
88
|
-
unicode-display_width (>= 2.4.0, <
|
|
89
|
-
rubocop-ast (1.
|
|
90
|
-
parser (>= 3.3.
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
91
|
+
rubocop-ast (1.47.1)
|
|
92
|
+
parser (>= 3.3.7.2)
|
|
93
|
+
prism (~> 1.4)
|
|
94
|
+
rubocop-rspec (3.7.0)
|
|
95
|
+
lint_roller (~> 1.1)
|
|
96
|
+
rubocop (~> 1.72, >= 1.72.1)
|
|
93
97
|
ruby-progressbar (1.13.0)
|
|
94
98
|
securerandom (0.4.1)
|
|
95
99
|
simplecov (0.22.0)
|
|
96
100
|
docile (~> 1.1)
|
|
97
101
|
simplecov-html (~> 0.11)
|
|
98
102
|
simplecov_json_formatter (~> 0.1)
|
|
99
|
-
simplecov-html (0.13.
|
|
103
|
+
simplecov-html (0.13.2)
|
|
100
104
|
simplecov_json_formatter (0.1.4)
|
|
101
105
|
stringio (3.1.7)
|
|
102
106
|
tsort (0.2.0)
|
|
103
107
|
tzinfo (2.0.6)
|
|
104
108
|
concurrent-ruby (~> 1.0)
|
|
105
|
-
unicode-display_width (2.
|
|
109
|
+
unicode-display_width (3.2.0)
|
|
110
|
+
unicode-emoji (~> 4.1)
|
|
111
|
+
unicode-emoji (4.1.0)
|
|
106
112
|
uri (1.0.4)
|
|
107
113
|
|
|
108
114
|
PLATFORMS
|
data/Readme.md
CHANGED
|
@@ -77,6 +77,10 @@ You can also manually set the current ID, if you already have it for a given mem
|
|
|
77
77
|
api.imis_id = imis_id
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
+
#### Without an iMIS ID
|
|
81
|
+
|
|
82
|
+
Running requests without an iMIS ID set will result in query results returned from the API.
|
|
83
|
+
|
|
80
84
|
### Business Object and Panel Actions
|
|
81
85
|
|
|
82
86
|
Business Objects and Panels support the following actions.
|
|
@@ -88,11 +92,15 @@ Panels require passing in the ordinal identifier as an argument, except for `POS
|
|
|
88
92
|
To fetch member data, run e.g.:
|
|
89
93
|
|
|
90
94
|
```ruby
|
|
91
|
-
api.imis_id = 31092
|
|
92
|
-
|
|
93
95
|
data = api.on('ABC_ASC_Individual_Demog').get
|
|
94
96
|
```
|
|
95
97
|
|
|
98
|
+
You can also pass in specific field names to filter the returned member data, e.g.:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
data = api.on('ABC_ASC_Individual_Demog').get('TotMMS', 'MMS_Updated')
|
|
102
|
+
```
|
|
103
|
+
|
|
96
104
|
Alias: `read`
|
|
97
105
|
|
|
98
106
|
#### GET Field
|
|
@@ -100,20 +108,26 @@ Alias: `read`
|
|
|
100
108
|
To fetch a specific field from member data, run e.g.:
|
|
101
109
|
|
|
102
110
|
```ruby
|
|
103
|
-
api.imis_id = 31092
|
|
104
|
-
|
|
105
111
|
tot_mms = api.on('ABC_ASC_Individual_Demog').get_field('TotMMS')
|
|
106
112
|
```
|
|
107
113
|
|
|
108
114
|
Alias: `fetch`
|
|
109
115
|
|
|
116
|
+
#### GET Fields
|
|
117
|
+
|
|
118
|
+
To fetch multiple specific fields from member data, run e.g.:
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
data = api.on('ABC_ASC_Individual_Demog').get_fields('TotMMS', 'MMS_Updated')
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Alias: `fetch_all`
|
|
125
|
+
|
|
110
126
|
#### PUT Fields
|
|
111
127
|
|
|
112
128
|
To update member data, run e.g.:
|
|
113
129
|
|
|
114
130
|
```ruby
|
|
115
|
-
api.imis_id = 31092
|
|
116
|
-
|
|
117
131
|
data = { 'MMS_Updated' => Time.now.strftime('%Y-%m-%dT%H:%M:%S'), 'TotMMS' => new_total }
|
|
118
132
|
update = api.on('ABC_ASC_Individual_Demog').put_fields(data)
|
|
119
133
|
```
|
|
@@ -128,8 +142,6 @@ Alias: `patch`
|
|
|
128
142
|
To update member data, run e.g.:
|
|
129
143
|
|
|
130
144
|
```ruby
|
|
131
|
-
api.imis_id = 31092
|
|
132
|
-
|
|
133
145
|
update = api.on('ABC_ASC_Individual_Demog').put(complete_imis_object)
|
|
134
146
|
```
|
|
135
147
|
|
|
@@ -156,8 +168,6 @@ Alias: `create`
|
|
|
156
168
|
To remove member data, run e.g.:
|
|
157
169
|
|
|
158
170
|
```ruby
|
|
159
|
-
api.imis_id = 31092
|
|
160
|
-
|
|
161
171
|
api.on('ABC_ASC_Individual_Demog').delete
|
|
162
172
|
```
|
|
163
173
|
|
|
@@ -200,25 +210,27 @@ For supported panels (usually, business objects with composite identity keys), y
|
|
|
200
210
|
with them in the same general way:
|
|
201
211
|
|
|
202
212
|
```ruby
|
|
203
|
-
vsc = Usps::Imis::
|
|
204
|
-
|
|
205
|
-
vsc.api.imis_id = 6374
|
|
213
|
+
vsc = Usps::Imis::Panels::Vsc.new(imis_id: 6374)
|
|
206
214
|
|
|
207
215
|
vsc.get(1417)
|
|
208
216
|
|
|
217
|
+
vsc.get_field(1417, 'Quantity')
|
|
218
|
+
|
|
209
219
|
created = vsc.create(certificate: 'E136924', year: 2024, count: 42)
|
|
210
220
|
ordinal = created['Properties']['$values'].find { it['Name'] == 'Ordinal' }['Value']['$value']
|
|
211
221
|
# ordinal = created['Identity']['IdentityElements']['$values'][1] # Alternative
|
|
212
222
|
|
|
213
223
|
vsc.update(certificate: 'E136924', year: 2024, count: 43, ordinal: ordinal)
|
|
214
224
|
|
|
225
|
+
vsc.put_fields(ordinal, 'Quantity' => 44)
|
|
226
|
+
|
|
215
227
|
vsc.destroy(ordinal)
|
|
216
228
|
```
|
|
217
229
|
|
|
218
230
|
If you already have an iMIS ID to work with, you can pass that in immediately:
|
|
219
231
|
|
|
220
232
|
```ruby
|
|
221
|
-
vsc = Usps::Imis::
|
|
233
|
+
vsc = Usps::Imis::Panels::Vsc.new(imis_id: imis_id)
|
|
222
234
|
```
|
|
223
235
|
|
|
224
236
|
Panels are also accessible directly from the API object:
|
|
@@ -270,9 +282,21 @@ end
|
|
|
270
282
|
api.with(31092).on('ABC_ASC_Individual_Demog').get_field('TotMMS')
|
|
271
283
|
```
|
|
272
284
|
|
|
285
|
+
## Test Data Mocking
|
|
286
|
+
|
|
287
|
+
You can use the provided Business Object Mock to generate stub data for rspec:
|
|
288
|
+
|
|
289
|
+
```ruby
|
|
290
|
+
allow(api).to(
|
|
291
|
+
receive(:on).with('ABC_ASC_Individual_Demog').and_return(
|
|
292
|
+
Usps::Imis::Mocks::BusinessObject.new(TotMMS: 2)
|
|
293
|
+
)
|
|
294
|
+
)
|
|
295
|
+
```
|
|
296
|
+
|
|
273
297
|
## Exception Handling
|
|
274
298
|
|
|
275
|
-
All internal exceptions inherit from `Usps::Imis::
|
|
299
|
+
All internal exceptions inherit from `Usps::Imis::Error`.
|
|
276
300
|
|
|
277
301
|
## Automated Testing and Linting
|
|
278
302
|
|
data/lib/usps/imis/api.rb
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'requests'
|
|
4
|
+
require_relative 'business_object'
|
|
5
|
+
require_relative 'mapper'
|
|
6
|
+
|
|
3
7
|
module Usps
|
|
4
8
|
module Imis
|
|
5
9
|
# The core API wrapper
|
|
@@ -48,7 +52,7 @@ module Usps
|
|
|
48
52
|
# @param id [Integer, String] iMIS ID to select for future requests
|
|
49
53
|
#
|
|
50
54
|
def imis_id=(id)
|
|
51
|
-
raise
|
|
55
|
+
raise Errors::LockedIdError if lock_imis_id
|
|
52
56
|
|
|
53
57
|
@imis_id = id&.to_i&.to_s
|
|
54
58
|
end
|
|
@@ -60,13 +64,13 @@ module Usps
|
|
|
60
64
|
# @return [String] Corresponding iMIS ID
|
|
61
65
|
#
|
|
62
66
|
def imis_id_for(certificate)
|
|
63
|
-
raise
|
|
67
|
+
raise Errors::LockedIdError if lock_imis_id
|
|
64
68
|
|
|
65
69
|
begin
|
|
66
70
|
result = query(Imis.configuration.imis_id_query_name, { certificate: })
|
|
67
71
|
@imis_id = result['Items']['$values'][0]['ID']
|
|
68
72
|
rescue StandardError
|
|
69
|
-
raise
|
|
73
|
+
raise Errors::NotFoundError, 'Member not found'
|
|
70
74
|
end
|
|
71
75
|
end
|
|
72
76
|
|
|
@@ -162,10 +166,7 @@ module Usps
|
|
|
162
166
|
# +Api+
|
|
163
167
|
#
|
|
164
168
|
def panels
|
|
165
|
-
@panels ||=
|
|
166
|
-
Panel::Vsc.new(self),
|
|
167
|
-
Panel::Education.new(self)
|
|
168
|
-
)
|
|
169
|
+
@panels ||= Panels.all(self)
|
|
169
170
|
end
|
|
170
171
|
|
|
171
172
|
# Ruby 3.5 instance variable filter
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'requests'
|
|
4
|
+
|
|
3
5
|
module Usps
|
|
4
6
|
module Imis
|
|
5
7
|
# DEV
|
|
@@ -32,28 +34,35 @@ module Usps
|
|
|
32
34
|
|
|
33
35
|
# Get a business object for the current member
|
|
34
36
|
#
|
|
35
|
-
#
|
|
37
|
+
# If +fields+ is provided, will return only those field values
|
|
36
38
|
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
# @param fields [String] Field names to return
|
|
40
|
+
#
|
|
41
|
+
# @return [Hash, Array<Hash>] Response data from the API
|
|
42
|
+
#
|
|
43
|
+
def get(*fields) = fields.any? ? get_fields(*fields) : raw_object
|
|
42
44
|
alias read get
|
|
43
45
|
|
|
44
46
|
# Get a single named field from a business object for the current member
|
|
45
47
|
#
|
|
46
|
-
# @param
|
|
48
|
+
# @param field [String] Field name to return
|
|
47
49
|
#
|
|
48
50
|
# @return [Hash] Response data from the API
|
|
49
51
|
#
|
|
50
|
-
def get_field(
|
|
51
|
-
|
|
52
|
-
value = values.find { it['Name'] == name }['Value']
|
|
52
|
+
def get_field(field) = extract_field_value(raw_object_values, field)
|
|
53
|
+
alias fetch get_field
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
# Get named fields from a business object for the current member
|
|
56
|
+
#
|
|
57
|
+
# @param names [Array<String>] Field names to return
|
|
58
|
+
#
|
|
59
|
+
# @return [Array<Hash>] Response data from the API
|
|
60
|
+
#
|
|
61
|
+
def get_fields(*fields)
|
|
62
|
+
values = raw_object_values
|
|
63
|
+
fields.map { extract_field_value(values, it) }
|
|
55
64
|
end
|
|
56
|
-
alias
|
|
65
|
+
alias fetch_all get_fields
|
|
57
66
|
|
|
58
67
|
# Update only specific fields on a business object for the current member
|
|
59
68
|
#
|
|
@@ -61,10 +70,7 @@ module Usps
|
|
|
61
70
|
#
|
|
62
71
|
# @return [Hash] Response data from the API
|
|
63
72
|
#
|
|
64
|
-
def put_fields(fields)
|
|
65
|
-
updated = filter_fields(fields)
|
|
66
|
-
put(updated)
|
|
67
|
-
end
|
|
73
|
+
def put_fields(fields) = put(filter_fields(fields))
|
|
68
74
|
alias patch put_fields
|
|
69
75
|
|
|
70
76
|
# Update a business object for the current member
|
|
@@ -75,12 +81,7 @@ module Usps
|
|
|
75
81
|
#
|
|
76
82
|
# @return [Hash] Response data from the API
|
|
77
83
|
#
|
|
78
|
-
def put(body)
|
|
79
|
-
request = Net::HTTP::Put.new(uri)
|
|
80
|
-
request.body = JSON.dump(body)
|
|
81
|
-
result = submit(uri, authorize(request))
|
|
82
|
-
JSON.parse(result.body)
|
|
83
|
-
end
|
|
84
|
+
def put(body) = put_object(Net::HTTP::Put.new(uri), body)
|
|
84
85
|
alias update put
|
|
85
86
|
|
|
86
87
|
# Create a business object for the current member
|
|
@@ -89,23 +90,14 @@ module Usps
|
|
|
89
90
|
#
|
|
90
91
|
# @return [Hash] Response data from the API
|
|
91
92
|
#
|
|
92
|
-
def post(body)
|
|
93
|
-
request = Net::HTTP::Post.new(uri(id: ''))
|
|
94
|
-
request.body = JSON.dump(body)
|
|
95
|
-
result = submit(uri, authorize(request))
|
|
96
|
-
JSON.parse(result.body)
|
|
97
|
-
end
|
|
93
|
+
def post(body) = put_object(Net::HTTP::Post.new(uri(id: '')), body)
|
|
98
94
|
alias create post
|
|
99
95
|
|
|
100
96
|
# Remove a business object for the current member
|
|
101
97
|
#
|
|
102
|
-
# @return [
|
|
98
|
+
# @return [true] Only on success response (i.e. blank string from the API)
|
|
103
99
|
#
|
|
104
|
-
def delete
|
|
105
|
-
request = Net::HTTP::Delete.new(uri)
|
|
106
|
-
result = submit(uri, authorize(request))
|
|
107
|
-
result.body
|
|
108
|
-
end
|
|
100
|
+
def delete = submit(uri, authorize(Net::HTTP::Delete.new(uri))).body == '' # rubocop:disable Naming/PredicateMethod
|
|
109
101
|
alias destroy delete
|
|
110
102
|
|
|
111
103
|
private
|
|
@@ -157,6 +149,35 @@ module Usps
|
|
|
157
149
|
end
|
|
158
150
|
end
|
|
159
151
|
end
|
|
152
|
+
|
|
153
|
+
# Get a raw object response from the API
|
|
154
|
+
#
|
|
155
|
+
# Useful for stubbing data in tests
|
|
156
|
+
#
|
|
157
|
+
def raw_object
|
|
158
|
+
request = Net::HTTP::Get.new(uri)
|
|
159
|
+
result = submit(uri, authorize(request))
|
|
160
|
+
JSON.parse(result.body)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Get just the property values from an object response from the API
|
|
164
|
+
#
|
|
165
|
+
def raw_object_values
|
|
166
|
+
raw_object['Properties']['$values']
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def extract_field_value(values, field)
|
|
170
|
+
value = values.find { it['Name'] == field }['Value']
|
|
171
|
+
value.is_a?(String) ? value : value['$value']
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Upload an object to the API
|
|
175
|
+
#
|
|
176
|
+
def put_object(request, body)
|
|
177
|
+
request.body = JSON.dump(body)
|
|
178
|
+
result = submit(uri, authorize(request))
|
|
179
|
+
JSON.parse(result.body)
|
|
180
|
+
end
|
|
160
181
|
end
|
|
161
182
|
end
|
|
162
183
|
end
|
data/lib/usps/imis/config.rb
CHANGED
|
@@ -32,7 +32,7 @@ module Usps
|
|
|
32
32
|
return IMIS_ROOT_URL_PROD if environment.production?
|
|
33
33
|
return IMIS_ROOT_URL_DEV if environment.development?
|
|
34
34
|
|
|
35
|
-
raise
|
|
35
|
+
raise Errors::ConfigError, "Unexpected API environment: #{environment}"
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
# Ruby 3.5 instance variable filter
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
# Base error class for all internal exceptions
|
|
6
|
+
#
|
|
7
|
+
class Error < StandardError
|
|
8
|
+
# Additional call-specific metadata to pass through to Bugsnag
|
|
9
|
+
#
|
|
10
|
+
attr_accessor :metadata
|
|
11
|
+
|
|
12
|
+
# A new instance of +ApiError+
|
|
13
|
+
#
|
|
14
|
+
# @param message [String] The base exception message
|
|
15
|
+
# @param metadata [Hash] Additional call-specific metadata to pass through to Bugsnag
|
|
16
|
+
#
|
|
17
|
+
def initialize(message, metadata = {})
|
|
18
|
+
super(message)
|
|
19
|
+
@metadata = metadata
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Additional metadata to include in Bugsnag reports
|
|
23
|
+
#
|
|
24
|
+
# Can include fields at the top level, which will be shows on the custom tab
|
|
25
|
+
#
|
|
26
|
+
# Can include fields nested under a top-level key, which will be shown on a tab with the
|
|
27
|
+
# top-level key as its name
|
|
28
|
+
#
|
|
29
|
+
# @return [Hash]
|
|
30
|
+
#
|
|
31
|
+
def bugsnag_meta_data
|
|
32
|
+
metadata == {} ? {} : base_metadata
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def base_metadata
|
|
38
|
+
{ api: metadata }
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
require_relative 'errors/api_error'
|
|
45
|
+
require_relative 'errors/config_error'
|
|
46
|
+
require_relative 'errors/locked_id_error'
|
|
47
|
+
require_relative 'errors/mapper_error'
|
|
48
|
+
require_relative 'errors/not_found_error'
|
|
49
|
+
require_relative 'errors/response_error'
|
|
50
|
+
require_relative 'errors/panel_unimplemented_error'
|
|
51
|
+
require_relative 'errors/unexpected_property_type_error'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
module Errors
|
|
6
|
+
# Exception raised when attempting to change the iMIS ID while it is locked
|
|
7
|
+
#
|
|
8
|
+
class LockedIdError < Error
|
|
9
|
+
def initialize = super(message)
|
|
10
|
+
|
|
11
|
+
def message = 'Cannot change iMIS ID while locked'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
module Errors
|
|
6
|
+
# Exception raised by a +Mapper+
|
|
7
|
+
#
|
|
8
|
+
class MapperError < Error
|
|
9
|
+
# Create a new instance of +MapperError+
|
|
10
|
+
#
|
|
11
|
+
# @param metadata [Hash] Additional call-specific metadata to pass through to Bugsnag
|
|
12
|
+
#
|
|
13
|
+
def initialize(metadata = {})
|
|
14
|
+
@metadata = metadata
|
|
15
|
+
super(message, metadata)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Exception message including the unrecognized field
|
|
19
|
+
#
|
|
20
|
+
def message
|
|
21
|
+
<<~MESSAGE.chomp
|
|
22
|
+
Mapper does not recognize field: "#{metadata[:field_name]}".
|
|
23
|
+
Please report what data you are attempting to work with to ITCom leadership.
|
|
24
|
+
MESSAGE
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Usps
|
|
4
|
+
module Imis
|
|
5
|
+
module Errors
|
|
6
|
+
# Exception raised when a panel is missing required method definitions
|
|
7
|
+
#
|
|
8
|
+
class PanelUnimplementedError < Error
|
|
9
|
+
# Create a new instance of +PanelUnimplementedError+ from the class name and missing method
|
|
10
|
+
#
|
|
11
|
+
# @param class_name [String] Name of the Panel class that is missing a method definition
|
|
12
|
+
# @param method [String] Method definition that is not defined on the Panel
|
|
13
|
+
#
|
|
14
|
+
def self.from(class_name, method) = new(class_name, method)
|
|
15
|
+
|
|
16
|
+
# Create a new instance of +PanelUnimplementedError+
|
|
17
|
+
#
|
|
18
|
+
# @param class_name [String] Name of the Panel class that is missing a method definition
|
|
19
|
+
# @param method [String] Method definition that is not defined on the Panel
|
|
20
|
+
# @param metadata [Hash] Additional call-specific metadata to pass through to Bugsnag
|
|
21
|
+
#
|
|
22
|
+
def initialize(class_name, method, metadata = {})
|
|
23
|
+
@class_name = class_name
|
|
24
|
+
@method = method
|
|
25
|
+
super(message, metadata)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Exception message including the undefined method
|
|
29
|
+
#
|
|
30
|
+
def message = "#{@class_name} must implement ##{@method}"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|