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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -3
  3. data/Gemfile.lock +36 -30
  4. data/Readme.md +39 -15
  5. data/lib/usps/imis/api.rb +8 -7
  6. data/lib/usps/imis/business_object.rb +55 -34
  7. data/lib/usps/imis/config.rb +1 -1
  8. data/lib/usps/imis/error.rb +51 -0
  9. data/lib/usps/imis/errors/api_error.rb +11 -0
  10. data/lib/usps/imis/errors/config_error.rb +11 -0
  11. data/lib/usps/imis/errors/locked_id_error.rb +15 -0
  12. data/lib/usps/imis/errors/mapper_error.rb +29 -0
  13. data/lib/usps/imis/errors/not_found_error.rb +11 -0
  14. data/lib/usps/imis/errors/panel_unimplemented_error.rb +34 -0
  15. data/lib/usps/imis/{error → errors}/response_error.rb +4 -7
  16. data/lib/usps/imis/errors/unexpected_property_type_error.rb +31 -0
  17. data/lib/usps/imis/mapper.rb +1 -5
  18. data/lib/usps/imis/mocks/business_object.rb +37 -0
  19. data/lib/usps/imis/mocks.rb +11 -0
  20. data/lib/usps/imis/{panel → panels}/base_panel.rb +26 -22
  21. data/lib/usps/imis/{panel → panels}/education.rb +1 -1
  22. data/lib/usps/imis/{panel → panels}/vsc.rb +1 -1
  23. data/lib/usps/imis/panels.rb +25 -0
  24. data/lib/usps/imis/properties.rb +1 -1
  25. data/lib/usps/imis/requests.rb +1 -1
  26. data/lib/usps/imis/version.rb +1 -1
  27. data/lib/usps/imis.rb +5 -15
  28. data/spec/lib/usps/imis/api_spec.rb +5 -5
  29. data/spec/lib/usps/imis/business_object_spec.rb +35 -13
  30. data/spec/lib/usps/imis/config_spec.rb +1 -1
  31. data/spec/lib/usps/imis/{error/api_error_spec.rb → error_spec.rb} +1 -1
  32. data/spec/lib/usps/imis/{error → errors}/response_error_spec.rb +4 -4
  33. data/spec/lib/usps/imis/mapper_spec.rb +2 -2
  34. data/spec/lib/usps/imis/{business_object_mock_spec.rb → mocks/business_object_spec.rb} +1 -1
  35. data/spec/lib/usps/imis/panels/base_panel_spec.rb +33 -0
  36. data/spec/lib/usps/imis/{panel → panels}/education_spec.rb +12 -2
  37. data/spec/lib/usps/imis/{panel → panels}/vsc_spec.rb +2 -2
  38. data/spec/lib/usps/imis/properties_spec.rb +1 -1
  39. data/usps-imis-api.gemspec +1 -1
  40. metadata +23 -16
  41. data/lib/ext/hash.rb +0 -10
  42. data/lib/usps/imis/business_object_mock.rb +0 -35
  43. data/lib/usps/imis/error/api_error.rb +0 -44
  44. data/lib/usps/imis/error/mapper_error.rb +0 -11
  45. 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: 9d68eb23f00014bc9cb6173f716084f8eff9cedfc48e70507c07a35fe8e7b207
4
- data.tar.gz: fda5c7882bc758d9cfdd2889e734ff8c0d319f456e39bf1965f030765ec82a0e
3
+ metadata.gz: ca358fc80eed74b0335f6137f71e503fffbc84d6c396c8e1c23c90501eab5b36
4
+ data.tar.gz: 239111a5dfd7cb186fe358fc0227e3063744225cf619e12a91e994f639142e56
5
5
  SHA512:
6
- metadata.gz: bb42f257b1e4e6c6383dd9b1f37d68e9c89f358f98bfccb09c53190573da28b0259fabe27e12f50c5420daa8f009661e928463c19a48e854abd86b8dd34021f1
7
- data.tar.gz: a4fb539ef056e6936e1546b303ef8b20bf52a822185063d8b6eabc042eb5b3f2b2fceb5d0cff5959c40ce524175a137dd1821783af7eea495803342c1d065cff
6
+ metadata.gz: 2f31860395762aeead9f002f96867111758a8474ada928ba1369e3122b767f0b27052ed41157d8eac008fade27bdb779389cd65c74ad7cadbb87129ee9c238ff
7
+ data.tar.gz: 7c0f5eaae8592a93192e08ca4cf88e604629de246b8e2f9272880d19e39a218d01a027387720a6c289b7f4490bc6617b57c637ab00201868ecd36fd178748031
data/.rubocop.yml CHANGED
@@ -1,4 +1,4 @@
1
- require:
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.6.16)
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.3)
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.2)
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.5.1)
29
+ diff-lcs (1.6.2)
31
30
  docile (1.4.1)
32
- dotenv (3.1.4)
31
+ dotenv (3.1.8)
33
32
  drb (2.2.3)
34
- erb (5.0.3)
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.7.2)
43
- language_server-protocol (3.17.0.3)
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.26.3)
47
- parser (3.3.5.0)
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.2.1)
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.9.2)
64
+ regexp_parser (2.11.3)
64
65
  reline (0.6.2)
65
66
  io-console (~> 0.5)
66
- rspec (3.13.0)
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.1)
71
+ rspec-core (3.13.6)
71
72
  rspec-support (~> 3.13.0)
72
- rspec-expectations (3.13.3)
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.2)
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.1)
79
- rubocop (1.66.1)
79
+ rspec-support (3.13.6)
80
+ rubocop (1.81.6)
80
81
  json (~> 2.3)
81
- language_server-protocol (>= 3.17.0)
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.4, < 3.0)
86
- rubocop-ast (>= 1.32.2, < 2.0)
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, < 3.0)
89
- rubocop-ast (1.32.3)
90
- parser (>= 3.3.1.0)
91
- rubocop-rspec (3.1.0)
92
- rubocop (~> 1.61)
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.1)
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.6.0)
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::Panel::Vsc.new
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::Panel::Vsc.new(imis_id: imis_id)
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::ApiError`.
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 Error::ApiError, 'Cannot change iMIS ID while locked' if lock_imis_id
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 Error::ApiError, 'Cannot change iMIS ID while locked' if lock_imis_id
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 Error::ApiError, 'Member not found'
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 ||= Struct.new(:vsc, :education).new(
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
- # @return [Hash] Response data from the API
37
+ # If +fields+ is provided, will return only those field values
36
38
  #
37
- def get
38
- request = Net::HTTP::Get.new(uri)
39
- result = submit(uri, authorize(request))
40
- JSON.parse(result.body)
41
- end
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 name [String] Field name to return
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(name)
51
- values = get['Properties']['$values']
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
- value.is_a?(String) ? value : value['$value']
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 fetch get_field
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 [String] Error response body from the API, or empty string on success
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
@@ -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 Error::ApiError, "Unexpected API environment: #{environment}"
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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Usps
4
+ module Imis
5
+ module Errors
6
+ # Generic exception raised from within the gem
7
+ #
8
+ class ApiError < Error; end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Usps
4
+ module Imis
5
+ module Errors
6
+ # Exception raised for invalid configuration
7
+ #
8
+ class ConfigError < Error; end
9
+ end
10
+ end
11
+ end
@@ -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,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Usps
4
+ module Imis
5
+ module Errors
6
+ # Exception raised when the requested object cannot be found
7
+ #
8
+ class NotFoundError < Error; end
9
+ end
10
+ end
11
+ 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