xeme 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +286 -0
  3. data/lib/xeme.rb +613 -0
  4. metadata +45 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d484d6f5c5b9cfdf0ae85dd4a1ca69c46b2b1c7eed711eae02352b59d3c929fe
4
+ data.tar.gz: e8d0a6527bafc7dff93ba1cd584a4527114e5dc3a40b165c3c86baf9ece744a2
5
+ SHA512:
6
+ metadata.gz: 291925e898631853c7a64f49327954b0b1c309b73e330d511561dc5c017ae7b15ab51f0fc22264e5c800a80c59530733776eba813840c06e179fd7db221aa166
7
+ data.tar.gz: 13d3459ee59daf94a4bc2841ed308ec498b14f361ad8eb76abb0d919d44823ba2fdf4df19e3b93df89d54d3c0c9564fdaf408c6f7c60d352e22844a79746b4c1
data/README.md ADDED
@@ -0,0 +1,286 @@
1
+ # Xeme
2
+
3
+ Xeme provides a common format for returning the results of a process. In its
4
+ simplest use, you create a Xeme object and add errors as necessary:
5
+
6
+ require 'xeme'
7
+ xeme = Xeme.new
8
+ xeme.error 'error-1'
9
+
10
+ If there are any errors, such as in this first example, <tt>success</tt> returns false:
11
+
12
+ puts xeme.success # false
13
+
14
+ A Xeme object without any errors returns true for <tt>success</tt>:
15
+
16
+ xeme = Xeme.new
17
+ puts xeme.success # true
18
+
19
+ Xeme is a good way to report results that are more complex than just success or
20
+ failure. For example, consider the situation in which a record must have a name
21
+ field and an email field. If the record does not meet these requirements, it is
22
+ not sufficient to merely report success or failure, nor to just report that one
23
+ field or the other is missing. With Xeme you can report all of that information
24
+ in a single object:
25
+
26
+ xeme = Xeme.new
27
+ xeme.error 'name'
28
+ xeme.error 'email'
29
+
30
+ You can return the Xeme object to another Ruby process, or you can output it to
31
+ JSON for use in some other program:
32
+
33
+ puts xeme.to_json
34
+
35
+ # outputs:
36
+ {"success":false,"messages":{"errors":[{"id":"name"},{"id":"email"}]}}
37
+
38
+ You might prefer to add the <tt>pretty</tt> option for more readable output:
39
+
40
+ puts xeme.to_json('pretty'=>true)
41
+
42
+ # outputs:
43
+ {
44
+ "success": false,
45
+ "messages": {
46
+ "errors": [
47
+ {
48
+ "id": "name"
49
+ },
50
+ {
51
+ "id": "email"
52
+ }
53
+ ]
54
+ }
55
+ }
56
+
57
+ In some situations, it's useful to give details about the error. For example,
58
+ if the <tt>name</tt> field is too long, you can report not just that there is
59
+ an error in that field, but specifics about that error:
60
+
61
+ xeme.error('name') do |msg|
62
+ msg['too-long'] = true
63
+ msg['max-length'] = 45
64
+ end
65
+
66
+ That would produce a structure like this:
67
+
68
+ {
69
+ "success": false,
70
+ "messages": {
71
+ "errors": [
72
+ {
73
+ "id": "name",
74
+ "details": {
75
+ "too-long": true,
76
+ "max-length": 45
77
+ }
78
+ }
79
+ ]
80
+ }
81
+ }
82
+
83
+
84
+ You can also add warnings and notes. A warning indicates a problem but not an
85
+ actual failure. A note does not indicate any problem at all but just some
86
+ information that should be passed along.
87
+
88
+ xeme.warning 'database-reset'
89
+ xeme.note 'database ok'
90
+
91
+ It's often useful to add misc details to the results. For example, a database
92
+ query might result in some rows from a table. You might add these rows to the
93
+ <tt>misc</tt> property like this:
94
+
95
+ xeme = Xeme.new
96
+ xeme.misc['rows'] = []
97
+ xeme.misc['rows'].push 'a'
98
+ xeme.misc['rows'].push 'b'
99
+ xeme.misc['rows'].push 'c'
100
+ puts xeme.to_json('pretty'=>true)
101
+
102
+ # outputs:
103
+ {
104
+ "success": true,
105
+ "misc": {
106
+ "rows": [
107
+ "a",
108
+ "b",
109
+ "c"
110
+ ]
111
+ }
112
+ }
113
+
114
+ Xeme can input a Xeme JSON structure to make a new Xeme object:
115
+
116
+ # json
117
+ json = <<~'JSON'
118
+ {
119
+ "success": false,
120
+ "messages": {
121
+ "errors": [
122
+ { "id": "location" }
123
+ ]
124
+ }
125
+ }
126
+ JSON
127
+
128
+ # xeme
129
+ xeme = Xeme.from_json(json)
130
+
131
+ ## Xeme structure
132
+
133
+ The Xeme structure can be used by any software, Ruby or otherwise, as a standard
134
+ way to report results. A Xeme structure can be stored in any format that
135
+ recognizes hashes, arrays, strings, numbers, booleans, and null. Such formats
136
+ include JSON and YAML. Xeme would be a good way for REST applications to
137
+ provide results from a query. The Xeme#to_json method outputs such a structure.
138
+ We'll use JSON for these examples.
139
+
140
+ An empty structure indicates success:
141
+
142
+ {}
143
+
144
+ That structure indicates no messages such as errors, and no details. To make the
145
+ structure easier to use by software that doesn't have a Xeme module, it is
146
+ customary to also output an explicit indication of success or failure:
147
+
148
+ {"success":true}
149
+
150
+ A Xeme structure can report any number of messages. A message is an error,
151
+ warning, or note. An error indicates that the process failed, and gives a resaon
152
+ why. If there are any errors, the process is considered a failure. A warning
153
+ indicates a problem, but not an actual failure. A note reports useful
154
+ information that does not indicate any kind of problem at all. Neither a warning
155
+ nor a note cause failure.
156
+
157
+ Messages, if any, are stored in a messages hash, which consists of arrays for
158
+ errors, warnings, and notes.
159
+
160
+ {
161
+ "success": false,
162
+ "messages": {
163
+ "errors": [
164
+ {
165
+ "id": "missing-city"
166
+ }
167
+ ],
168
+ "warnings": [
169
+ {
170
+ "id": "database-reset"
171
+ }
172
+ ],
173
+ "notes": [
174
+ {
175
+ "id": "database-online"
176
+ }
177
+ ]
178
+ }
179
+ }
180
+
181
+ Any number of messages can be reported. So, for example, the following structure
182
+ has two errors and no warnings or notes.
183
+
184
+ {
185
+ "success": false,
186
+ "messages": {
187
+ "errors": [
188
+ {
189
+ "id": "missing-city"
190
+ }
191
+ ],
192
+ "warnings": [
193
+ {
194
+ "id": "missing-zip-code"
195
+ }
196
+ ]
197
+ }
198
+ }
199
+
200
+ A message can have associated details. For example, the following error
201
+ indicates that the problem with the name field is that it's too long, and the
202
+ maximum length is 45:
203
+
204
+ {
205
+ "success": false,
206
+ "messages": {
207
+ "errors": [
208
+ {
209
+ "id": "name",
210
+ "details": {
211
+ "too-long": true,
212
+ "max-length": 45
213
+ }
214
+ }
215
+ ]
216
+ }
217
+ }
218
+
219
+ Sometimes it is useful to add arbitrary information to the results. For example,
220
+ the results from a database query might return the rows that the query produced.
221
+ In that situation, the misc element is handy.
222
+
223
+ {
224
+ "success": true,
225
+ "misc": {
226
+ "rows": [
227
+ "Fred",
228
+ "Mary",
229
+ "Jane"
230
+ ]
231
+ }
232
+ }
233
+
234
+ Sometimes it is useful to provide information about the specific transaction,
235
+ e.g. the call to a REST server. The transaction element can be used to provide
236
+ that information. If there is a transaction element, it should always provide a
237
+ timestamp for the transaction and a unique ID for it.
238
+
239
+ {
240
+ "success": true,
241
+ "transaction": {
242
+ "response": "08214643960776591",
243
+ "timestamp": "2020-01-07T18:41:37+00:00"
244
+ }
245
+ }
246
+
247
+ If the request includes an ID for that specific request, then that ID can be
248
+ supplied as part of the transaction element:
249
+
250
+ {
251
+ "success": true,
252
+ "transaction": {
253
+ "request": "64e57c8a-bd3e-47b9-9221-e9e3e0263341",
254
+ "response": "3301315461336113",
255
+ "timestamp": "2020-01-07T18:42:01+00:00"
256
+ }
257
+ }
258
+
259
+ The general adoption of the Xeme structure could simplify implementing
260
+ interoperable applications such as REST APIs.
261
+
262
+ ## The name
263
+
264
+ The word "xeme" has no particular association with the concept of results
265
+ reporting. I got the word from a random word generator and I liked it. The xeme,
266
+ also known as Sabine's gull, is a type of gull. See
267
+ [the Wikipedia page](https://en.wikipedia.org/wiki/Sabine's_gull)
268
+ if you'd like to know more.
269
+
270
+ ## Install
271
+
272
+ ```
273
+ gem install xeme
274
+ ```
275
+
276
+ ## Author
277
+
278
+ Mike O'Sullivan
279
+ mike@idocs.com
280
+
281
+ ## History
282
+
283
+ | version | date | notes |
284
+ |---------|-------------|-----------------|
285
+ | 0.1 | Jan 7, 2020 | Initial upload. |
286
+
data/lib/xeme.rb ADDED
@@ -0,0 +1,613 @@
1
+ require 'date'
2
+ require 'json'
3
+ require 'forwardable'
4
+
5
+ #===============================================================================
6
+ # Xeme
7
+ #
8
+
9
+ ##
10
+ # Objects of this class represent a set of results. See the README file for
11
+ # more details.
12
+
13
+ class Xeme
14
+ # Version 0.1
15
+ VERSION = '0.1'
16
+
17
+ # A Xeme::Messages object, which is basically just a hash containing arrays
18
+ # for errors, warnings, and notes.
19
+ attr_reader :messages
20
+
21
+ # A hash of any miscellaneous details you want to include.
22
+ attr_reader :misc
23
+
24
+ #---------------------------------------------------------------------------
25
+ # initialize
26
+ #
27
+
28
+ ##
29
+ # new() does not take any parameters.
30
+
31
+ def initialize
32
+ # initialize errors, warnings, notes, misc
33
+ @messages = Xeme::Messages.new
34
+ @misc = {}
35
+
36
+ # prefix and auto_misc
37
+ @prefixes = []
38
+ @auto_details_val = nil
39
+
40
+ # transaction
41
+ @transaction = nil
42
+ end
43
+ #
44
+ # initialize
45
+ #---------------------------------------------------------------------------
46
+
47
+
48
+ #---------------------------------------------------------------------------
49
+ # errors, warnings, notes
50
+ #
51
+
52
+ ##
53
+ # Returns the array of errors.
54
+ def errors
55
+ return @messages['errors']
56
+ end
57
+
58
+ ##
59
+ # Returns the array of warnings.
60
+ def warnings
61
+ return @messages['warnings']
62
+ end
63
+
64
+ ##
65
+ # Returns the array of notes.
66
+ def notes
67
+ return @messages['notes']
68
+ end
69
+ #
70
+ # errors, warnings, notes
71
+ #---------------------------------------------------------------------------
72
+
73
+
74
+ #---------------------------------------------------------------------------
75
+ # transaction
76
+ #
77
+
78
+ ##
79
+ # Returns the transaction object, creating it if necessary. See
80
+ # Xeme::Transaction. If the transaction object is never created then it is
81
+ # not output with #to_json. The transaction object can be used to provide
82
+ # meta information about the request and response that produced the
83
+ # results. See Xeme::Transaction for more information.
84
+ #
85
+ # You can create the transaction object by simply calling this method:
86
+ #
87
+ # xeme.transaction
88
+ #
89
+ # If you want to assign a request ID, call this method and assign to its
90
+ # request property. For example, if there's a request object that provides
91
+ # an id, you could assign the transaction.request ID like this:
92
+ #
93
+ # xeme.transaction.request = request.id
94
+
95
+ def transaction
96
+ @transaction ||= Xeme::Transaction.new()
97
+ return @transaction
98
+ end
99
+ #
100
+ # transaction
101
+ #---------------------------------------------------------------------------
102
+
103
+
104
+ #---------------------------------------------------------------------------
105
+ # to_h
106
+ #
107
+
108
+ ##
109
+ # Returns a hash with all the results. This hash can be used to create a JSON
110
+ # object. Empty arrays, such as if there are no warnings, are not included.
111
+
112
+ def to_h
113
+ # $tm.hrm
114
+
115
+ # initialize return value
116
+ rv = {}
117
+
118
+ # success
119
+ rv['success'] = success()
120
+
121
+ # transaction
122
+ if @transaction
123
+ rv['transaction'] = @transaction.to_h
124
+ end
125
+
126
+ # if any messages
127
+ if @messages.any?
128
+ msgs = rv['messages'] = {}
129
+
130
+ @messages.each do |key, arr|
131
+ if arr.any?
132
+ msgs[key] = []
133
+
134
+ arr.each do |msg|
135
+ msgs[key].push msg.to_h
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ # misc
142
+ if @misc.any?
143
+ rv['misc'] = @misc
144
+ end
145
+
146
+ # return
147
+ return rv
148
+ end
149
+ #
150
+ # to_h
151
+ #---------------------------------------------------------------------------
152
+
153
+
154
+ #---------------------------------------------------------------------------
155
+ # to_json
156
+ #
157
+
158
+ ##
159
+ # Returns a JSON string containing all the result information.
160
+ def to_json(opts={})
161
+ if opts['pretty']
162
+ return JSON.pretty_generate(self.to_h)
163
+ else
164
+ return JSON.generate(self.to_h)
165
+ end
166
+ end
167
+ #
168
+ # to_json
169
+ #---------------------------------------------------------------------------
170
+
171
+
172
+ #---------------------------------------------------------------------------
173
+ # success
174
+ #
175
+
176
+ ##
177
+ # Returns false if there are any errors, true otherwise.
178
+
179
+ def success
180
+ return @messages['errors'].empty?
181
+ end
182
+
183
+ ##
184
+ # Returns the opposite of <tt>success()</tt>.
185
+ def failure
186
+ return success ? false : true
187
+ end
188
+
189
+ #
190
+ # success
191
+ #---------------------------------------------------------------------------
192
+
193
+
194
+ #---------------------------------------------------------------------------
195
+ # exception
196
+ #
197
+
198
+ ##
199
+ # Use this method to hold on to details about an exception. An error object
200
+ # will be created, along with the exception's to_s backtrace.
201
+
202
+ def exception(id, e, details={})
203
+ message = self.error(id, details)
204
+ message.details['error'] = e.to_s
205
+ message.details['backtrace'] = e.backtrace
206
+ end
207
+ #
208
+ # exception
209
+ #---------------------------------------------------------------------------
210
+
211
+
212
+ #---------------------------------------------------------------------------
213
+ # prefix
214
+ #
215
+
216
+ ##
217
+ # <tt>prefix</tt> allows you to automatically add prefixes to your message
218
+ # codes in situations where many messages will start with the same string.
219
+ # Consider the following situation.
220
+ #
221
+ # xeme.error '/virginia/slope'
222
+ # xeme.error '/virginia/angle'
223
+ # xeme.error '/virginia/departure'
224
+ #
225
+ # That works, but the redundancy can get confusing (and annoying). With
226
+ # <tt>prefix</tt> you can avoid the redundancy like this:
227
+ #
228
+ # xeme.prefix('virginia') do
229
+ # xeme.error 'slope'
230
+ # xeme.error 'angle'
231
+ # xeme.error 'departure'
232
+ # end
233
+ #
234
+ # puts xeme.errors[0].id # /virginia/slope
235
+ # puts xeme.errors[1].id # /virginia/angle
236
+ # puts xeme.errors[2].id # /virginia/departure
237
+ #
238
+ # Prefixes can also be nested, like this:
239
+ #
240
+ # xeme.prefix('virginia') do
241
+ # xeme.prefix('fairfax') do
242
+ # xeme.error 'slope'
243
+ # end
244
+ # end
245
+ #
246
+ # puts xeme.errors[0].id # /virginia/fairfax/slope
247
+
248
+ def prefix(p_prefix)
249
+ # $tm.hrm
250
+ hold_prefixes = @prefixes.clone
251
+ @prefixes = @prefixes.clone
252
+ @prefixes.push p_prefix
253
+
254
+ begin
255
+ yield
256
+ ensure
257
+ @prefixes = hold_prefixes
258
+ end
259
+ end
260
+ #
261
+ # prefix
262
+ #---------------------------------------------------------------------------
263
+
264
+
265
+ #---------------------------------------------------------------------------
266
+ # error, warning, note
267
+ #
268
+
269
+ ##
270
+ # Creates a message object and stores it in the errors array.
271
+ #
272
+ # xeme.error('error-1').
273
+ #
274
+ # A hash of arbitrary details can be given. Those details will be stored
275
+ # with the message object in its Xeme::Message#details property.
276
+ #
277
+ # xeme.error('error-0', 'choice'=>'a')
278
+ #
279
+ # This method returns the message object, which can be used as another
280
+ # way to store details.
281
+ #
282
+ # msg = xeme.error('error-1').
283
+ # msg['location'] = 1
284
+ #
285
+ # If a block is given, the block is called with the error object as the
286
+ # single param.
287
+ #
288
+ # xeme.error('error-2') do |error|
289
+ # error['location'] = 2
290
+ # end
291
+ def error(id, details={}, &block)
292
+ return add_comment(Xeme::Message, 'errors', id, details={}, &block)
293
+ end
294
+
295
+ ##
296
+ # Works just #error() except it stores the message in the warnings array.
297
+ def warning(id, details={}, &block)
298
+ return add_comment(Xeme::Message, 'warnings', id, details={}, &block)
299
+ end
300
+
301
+ ##
302
+ # Works just #error() except it stores the message in the notes array.
303
+ def note(id, details={}, &block)
304
+ return add_comment(Xeme::Message, 'notes', id, details={}, &block)
305
+ end
306
+ #
307
+ # error, warning, note
308
+ #---------------------------------------------------------------------------
309
+
310
+
311
+ #---------------------------------------------------------------------------
312
+ # from_json
313
+ #
314
+
315
+ ##
316
+ # Creates a new Xeme object from a JSON structure.
317
+
318
+ def self.from_json(raw_json)
319
+ # $tm.hrm
320
+ hsh = JSON.parse(raw_json)
321
+ rv = self.new
322
+
323
+ # explicit success or failure
324
+ if not hsh['success'].nil?
325
+ rv.success = hsh['success']
326
+ end
327
+
328
+ # messages
329
+ if messages = hsh['messages']
330
+ messages.each do |msg_type, arr|
331
+ rv.messages[msg_type] ||= []
332
+ rv.messages[msg_type] += arr
333
+ end
334
+ end
335
+
336
+ # return
337
+ return rv
338
+ end
339
+ #
340
+ # from_json
341
+ #---------------------------------------------------------------------------
342
+
343
+
344
+ # private methods
345
+ private
346
+
347
+
348
+ #---------------------------------------------------------------------------
349
+ # messages_to_h
350
+ #
351
+ def messages_to_h(arr)
352
+ rv = []
353
+
354
+ # messages
355
+ arr.each do |msg|
356
+ rv.push msg.to_h
357
+ end
358
+
359
+ # return
360
+ return rv
361
+ end
362
+ #
363
+ # messages_to_h
364
+ #---------------------------------------------------------------------------
365
+
366
+
367
+ #---------------------------------------------------------------------------
368
+ # add_comment
369
+ #
370
+ def add_comment(cls, type, id, details={}, &block)
371
+ # $tm.hrm
372
+
373
+ # build message
374
+ msg = cls.new(prefix_id(id), details)
375
+
376
+ # ensure array
377
+ @messages[type] ||= []
378
+
379
+ # add to errors array
380
+ @messages[type].push(msg)
381
+
382
+ # yield
383
+ if block_given?
384
+ yield msg
385
+ end
386
+
387
+ # return
388
+ return msg
389
+ end
390
+ #
391
+ # add_comment
392
+ #---------------------------------------------------------------------------
393
+
394
+
395
+ #---------------------------------------------------------------------------
396
+ # prefix_id
397
+ #
398
+ def prefix_id(p_id)
399
+ if @prefixes.any?
400
+ return '/' + @prefixes.join('/') + '/' + p_id
401
+ else
402
+ return p_id
403
+ end
404
+ end
405
+ #
406
+ # prefix_id
407
+ #---------------------------------------------------------------------------
408
+ end
409
+ #
410
+ # Xeme
411
+ #===============================================================================
412
+
413
+
414
+ #===============================================================================
415
+ # Xeme::Message
416
+ #
417
+
418
+ ##
419
+ # A Xeme::Message object represents a single error, warning, or note.
420
+ # It is the base class for Xeme::Message::Error,
421
+ # Xeme::Message::Warning, and
422
+ # Xeme::Message::Note. Don't instantiate Xeme::Message
423
+ # directly, use Xeme#error, Xeme#warning, or Xeme#note.
424
+ #
425
+ # Each message contains at least an id. It can also have an options details
426
+ # hash which can be used to store misc information about the message.
427
+ #
428
+ # The message itself can be treated like a hash to give details:
429
+ #
430
+ # msg = xeme.error('my-error')
431
+ # msg['location'] = 1
432
+
433
+ class Xeme::Message
434
+ # The id of the message.
435
+ attr_reader :id
436
+
437
+ # delegate to hsh
438
+ extend Forwardable
439
+ delegate %w([] []= each length clear delete) => :@details
440
+
441
+
442
+ #---------------------------------------------------------------------------
443
+ # initialize
444
+ #
445
+
446
+ # Initialize a Xeme::Message object with the id of the message. The id can
447
+ # be any string. The optional <tt>details</tt> hash will be stored with the
448
+ # message.
449
+
450
+ def initialize(id, details={})
451
+ # $tm.hr __method__
452
+
453
+ # set id
454
+ @id = id
455
+
456
+ # initialize details
457
+ @details = details.clone
458
+ end
459
+ #
460
+ # initialize
461
+ #---------------------------------------------------------------------------
462
+
463
+
464
+ #---------------------------------------------------------------------------
465
+ # to_h
466
+ #
467
+
468
+ ##
469
+ # Returns a hash structure of the message. This structure is used by
470
+ # Xeme#to_h.
471
+
472
+ def to_h
473
+ rv = {}
474
+ rv['id'] = @id
475
+
476
+ if @details.any?
477
+ rv['details'] = @details
478
+ end
479
+
480
+ return rv
481
+ end
482
+ #
483
+ # to_h
484
+ #---------------------------------------------------------------------------
485
+ end
486
+ #
487
+ # Xeme::Message
488
+ #===============================================================================
489
+
490
+
491
+ #===============================================================================
492
+ # Xeme::Messages
493
+ #
494
+
495
+ ##
496
+ # This object holds the arrays of errors, warnings, and notes. It can mostly be
497
+ # treated like a hash. The main difference between a Xeme::Messages object and
498
+ # a hash is that any? returns true or false based on if there are any messages,
499
+ # not if there are any elements in the hash.
500
+
501
+ class Xeme::Messages
502
+ # delegate to hsh
503
+ extend Forwardable
504
+ delegate %w([] []= each length keys has_key?) => :@hsh
505
+
506
+ #---------------------------------------------------------------------------
507
+ # initialize
508
+ #
509
+
510
+ ##
511
+ # new() takes no parameters.
512
+
513
+ def initialize
514
+ @hsh = {}
515
+ @hsh['errors'] = []
516
+ @hsh['warnings'] = []
517
+ @hsh['notes'] = []
518
+ end
519
+ #
520
+ # initialize
521
+ #---------------------------------------------------------------------------
522
+
523
+
524
+ #---------------------------------------------------------------------------
525
+ # any?
526
+ #
527
+
528
+ ##
529
+ # Returns if there are any messages in any of the errors, warnings, or
530
+ # notes arrays.
531
+
532
+ def any?
533
+ @hsh.values.each do |arr|
534
+ arr.any? and return true
535
+ end
536
+
537
+ return false
538
+ end
539
+ #
540
+ # any?
541
+ #---------------------------------------------------------------------------
542
+ end
543
+ #
544
+ # Xeme::Messages
545
+ #===============================================================================
546
+
547
+
548
+ #===============================================================================
549
+ # Xeme::Transaction
550
+ #
551
+
552
+ ##
553
+ # An object of this class provdes meta information about the request and
554
+ # results. It always provides a a timestamp and a unique ID for the results. It
555
+ # may also optionally include a request ID that was provided by the process
556
+ # that made the request, such as a call to a REST application. Do not directly
557
+ # instantiate this class; use Xeme#transaction.
558
+
559
+ class Xeme::Transaction
560
+
561
+ # Optional. An ID for the request that was sent by the calling process. Do
562
+ # not generate this value yourself; use the ID that was sent with the
563
+ # request (if one was sent).
564
+ attr_accessor :request
565
+
566
+ # Gives a unique ID for these results.
567
+ attr_reader :response
568
+
569
+ # Gives a timestamp for when these results were generated.
570
+ attr_reader :timestamp
571
+
572
+ #---------------------------------------------------------------------------
573
+ # initialize
574
+ #
575
+
576
+ ##
577
+ # Initialize does not take any parameters.
578
+
579
+ def initialize
580
+ @timestamp = DateTime.now()
581
+ @response = rand().to_s.sub(/\A0\./mu, '')
582
+ @request = nil
583
+ end
584
+ #
585
+ # initialize
586
+ #---------------------------------------------------------------------------
587
+
588
+
589
+ #---------------------------------------------------------------------------
590
+ # to_h
591
+ #
592
+ def to_h
593
+ rv = {}
594
+
595
+ # request
596
+ if @request
597
+ rv['request'] = @request
598
+ end
599
+
600
+ # response and timestamp
601
+ rv['response'] = @response
602
+ rv['timestamp'] = @timestamp.to_s
603
+
604
+ # return
605
+ return rv
606
+ end
607
+ #
608
+ # to_h
609
+ #---------------------------------------------------------------------------
610
+ end
611
+ #
612
+ # Xeme::Transaction
613
+ #===============================================================================
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xeme
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Mike O'Sullivan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-01-06 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Provides a common means for reporting results between processes
14
+ email: mike@idocs.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - README.md
20
+ - lib/xeme.rb
21
+ homepage: https://rubygems.org/gems/xeme
22
+ licenses:
23
+ - MIT
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubyforge_project:
41
+ rubygems_version: 2.7.6
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: General purpose structure for reporting results
45
+ test_files: []