xeme 1.2 → 2.0

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 +4 -4
  2. data/README.md +306 -225
  3. data/lib/xeme.rb +694 -627
  4. metadata +25 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cdf9cdb30bbab1fe3155496c778a01c83fb35c011bb9d00c63525fffa1c5cec8
4
- data.tar.gz: aa5b17da3d91e1ab8940aa84ff38dd4fcbe5d274acebcb7483c4bf9221ed6dca
3
+ metadata.gz: ae47399bb72561b8d7d6efedeb37e43840269d5fb6ab686bdfc31499ee3595e8
4
+ data.tar.gz: 83c15744b30011cfd1cac0ee53771ee790f34a15b5983af1763b65000109bc64
5
5
  SHA512:
6
- metadata.gz: 98eab45cddd377c4a3c81d1de8c800e169b360fbe0451402256e57c18e412c971f6eef059795ad54134297228757728561e730a33271e932574d198028976f99
7
- data.tar.gz: 1200e1c8b64b5233c102e83414499fdc39db85df7d5cf071caee830a5e218a29c94f590b6d44b8ed2266d8c6fb5b34ee9112d2d7eeb97201a9d49fc57225bd0b
6
+ metadata.gz: 3486a1a926faea61cb880dba644cf8619c8615bdf22af79e37ab5a3777907eb0c20f81532f215d42be8cfb7dbaf0773f80cbf6b5f9f42c50a6d4bc781a1f26c8
7
+ data.tar.gz: 21e10be699393ea20c8e6bcd488f66d9f05647aa6f8c6c51a0b8ea6072ecea4f51a4920061fbd9b2f53d98766fd103048937dcb1386952486b8e505d3a21fec2
data/README.md CHANGED
@@ -19,8 +19,8 @@ A xeme can be as simple as an empty hash:
19
19
  ```
20
20
 
21
21
  That structure indicates no errors, and, in fact, no details at all. However, it
22
- also does not explicitly indicate success, so that xeme would be considered to
23
- have failed.
22
+ also does not explicitly indicate success. In the absence of a defined value of
23
+ true or false, the result should be considered either undetermined or failed.
24
24
 
25
25
  To indicate a successful operation, a xeme must have an explicit `success`
26
26
  element:
@@ -35,69 +35,235 @@ A xeme can be marked as explicitly failed:
35
35
  {"success":false}
36
36
  ```
37
37
 
38
- If a xeme does not have an explicit `success` element, or it is set to `nil`, it
39
- should be considered to have failed. However, depending on how you process the
40
- xeme, `nil` could be considered as having not finished the test. In that case,
41
- consider using [promises](#promises).
38
+ Any truthy value for `success` is considered to indicate success. So, for
39
+ example, the following xeme should be considered to indicate success.
42
40
 
43
- ### Messages
41
+ ```json
42
+ {"success":{}}
43
+ ```
44
44
 
45
- A message is an error, a warning, a note, or a promise. Each type of message has
46
- an array. For example, this xeme has two errors:
45
+ A xeme may contain other arbitrary information. This is useful if you need more
46
+ information than just a success or failure.
47
47
 
48
48
  ```json
49
- { "errors":[{"id":"http-fault"}, {"id":"transaction-error"}] }
49
+ {"success":true, "tags":["a", "b"]}
50
50
  ```
51
51
 
52
- A message does not have to have any particular structure, but best practice is
53
- to give each message an identifier (`id`).
52
+ ### Metainformation
54
53
 
55
- If there are any errors then that indicates a failure, regardless of the value
56
- of `success`. Any implementation of Xeme should have a method for resolving
57
- conflicts between `success` and `errors`, always giving priority to the presence
58
- of errors over the value of `success`.
54
+ A xeme may contain a `meta` element. The `meta` element can contain a timestamp,
55
+ UUID, description, or other meta information.
59
56
 
60
- If a xeme has any promises then that indicates not success, though not
61
- necessarily explicit failure. If a xeme is marked as successful, but there are
62
- promises, then `success` should be considered nil.
57
+ ```json
58
+ {
59
+ "success":true,
60
+ "meta": {
61
+ "timestamp": "2023-06-21T08:57:56+00:00",
62
+ "uuid": "e11b668c-0823-4b70-aa28-5ac83757a37c",
63
+ "description": "directory tests"
64
+ }
65
+ }
66
+ ```
63
67
 
64
- Warnings indicate problems that don't outright cause a failure. Notes are
65
- messages that don't indicate a problem of any kind.
68
+ `meta` can contain any arbitrary information you want, but several elements, if
69
+ present, should follow some standards.
66
70
 
67
- ### Metainformation
71
+ | key | description |
72
+ |-------------|----------------------------------------------|
73
+ | id | A string, typically without spaces. |
74
+ | description | A short description of the xeme as a string. |
75
+ | timestamp | Timestamp in a standard ISO 8601 format. |
76
+ | UUID | A UUID. |
77
+
78
+ ### Nested xemes
79
+
80
+ A xeme represents the results of a single process. However, a xeme can also
81
+ contain nested xemes which provide information about sub-processes. In this
82
+ sense, a xeme can be considered as the final results of the xemes nested within
83
+ it.
68
84
 
69
- Sometimes it's useful to store metainformation the xeme. For example, log files
70
- are more discoverable if each xeme has a unique id and timestamp. Generally a
71
- xeme will have at least to elements, `uuid` and `timestamp`:
85
+ Child xemes are contained in the `nested` array.
72
86
 
73
87
  ```json
74
88
  {
75
- "meta":{
76
- "uuid":"dae1cf26-e8fa-43fa-bedc-88fea10255f4",
77
- "timestamp":"2023-05-25 03:46:19 -0400"
78
- }
89
+ "success":true,
90
+ "meta": {"id":"directory"},
91
+ "nested":[
92
+ {"success":true, "meta": {"id":"database-connection"}},
93
+ {"success":true, "meta": {"id":"update"}}
94
+ ]
79
95
  }
80
96
  ```
81
97
 
82
- ### Nested xemes
98
+ Nested xemes can themselves have nested xemes, forming a tree of process
99
+ results.
100
+
101
+ ```json
102
+ {
103
+ "success":true,
104
+ "meta": {"id":"database"},
105
+ "nested": [
106
+ {
107
+ "success":true,
108
+ "meta": {"id":"database-connection"},
109
+ "nested": [
110
+ {"success":true, "meta":{"id":"initialization"}},
111
+ {"success":true, "meta":{"id":"disconnection"}}
112
+ ]
113
+ }
114
+ ]
115
+ }
116
+ ```
117
+
118
+ ### Resolution
119
+
120
+ Xeme operates on the concept of "least successful outcome". A xeme cannot
121
+ represent more success than its descendent xemes. So, for example, the following
122
+ structure contains conflicts:
123
+
124
+ ```json
125
+ {
126
+ "success":true,
127
+ "nested":[
128
+ {"success":false}
129
+ ]
130
+ }
131
+ ```
132
+
133
+ It is necessary to resolve these conflicts before the xeme can be considered
134
+ valid. A conforming processor should implement the following rules:
135
+
136
+ * If a xeme is marked as failure, all of its ancestor xemes should be marked
137
+ as failed. So the example above would be resolved as follows:
138
+
139
+ ```json
140
+ {
141
+ "success":false,
142
+ "nested":[
143
+ {"success":false}
144
+ ]
145
+ }
146
+ ```
147
+
148
+ A process can be marked as failed regardless of its nested xemes. So there is no
149
+ conflict in the following structure.
150
+
151
+ ```json
152
+ {
153
+ "success":false,
154
+ "nested":[
155
+ {"success":true}
156
+ ]
157
+ }
158
+ ```
159
+
160
+ * If a xeme's `success` is null, then all its ancestors' `success` values must
161
+ be set to null if they are not already set to false. The following structure is
162
+ invalid.
163
+
164
+ ```json
165
+ {
166
+ "success":true,
167
+ "nested":[
168
+ {"success":null}
169
+ ]
170
+ }
171
+ ```
172
+
173
+ It should be resolved as follows:
174
+
175
+ ```json
176
+ {
177
+ "success":null,
178
+ "nested":[
179
+ {"success":null}
180
+ ]
181
+ }
182
+ ```
183
+
184
+ ### Advisory and promise xemes
185
+
186
+ Three types of Xemes operate on a different ruleset than standard xemes. Those
187
+ types are warnings, notes, and promises. They are indicated by the `type`
188
+ property:
189
+
190
+ ```json
191
+ {"type": "warning"}
192
+ ```
193
+
194
+ #### Warnings and notes
195
+
196
+ Warnings and notes provide advisory information about a process. They have no
197
+ affect on the success/failure determination. Warnings provide information about
198
+ non-fatal problems in a prosess. Notes do not indicate problems of any kind and
199
+ simply provide whatever arbitrary information might be useful. Advisory xemes
200
+ should not have `success` properties. So, for example, the following structure
201
+ is valid, even though the nested advisory xemes do not have `success`
202
+ properties.
203
+
204
+ ```json
205
+ {
206
+ "success":true,
207
+ "nested":[
208
+ {"type":"warning", "id":"invalid-setting"},
209
+ {"type":"note", "id":"database-connected"}
210
+ ]
211
+ }
212
+ ```
213
+
214
+ Advisory xemes can have nested xemes. However, all descendents of an advisory
215
+ xeme should themselves be advisory.
216
+
217
+ #### Promises
218
+
219
+ A promise xeme indicates that the success/failure of a process has yet to be
220
+ determined. A promise should have a `success` value of null, unless it has also
221
+ has a truthy value in `supplanted`. For example, the following xemes are valid:
222
+
223
+ ```json
224
+ { "type":"promise" }
225
+ ```
226
+
227
+ ```json
228
+ { "type":"promise", "supplanted":true, "success": true }
229
+ ```
230
+
231
+ ```json
232
+ { "type":"promise", "supplanted":"2023-06-22T06:28:43+0000", "success": true }
233
+ ```
83
234
 
84
- A xeme can have nested xemes within it. Those nested xemes go in the `nested`
85
- array:
235
+ Typically, a promise should have an indication of how the promise can be
236
+ resolved. For example, the following xeme is a promise, with further information
237
+ to indicate a URI where the final result can be determined, and how soon to
238
+ query that URI.
86
239
 
87
240
  ```json
88
241
  {
89
- "nested": [
90
- { "success": true },
91
- { "errors": [{"id":"server-fault"}] },
92
- ]
242
+ "type":"promise",
243
+ "uri": "https://example.com/20435t",
244
+ "delay": 6000
93
245
  }
94
246
  ```
95
247
 
96
- For a xeme to be considered successful, all of its nested xemes must be marked
97
- as success. If any nested xemes have errors, then the outermost xeme is
98
- considered to be considered as failed. If any nested xemes has `success` as nil,
99
- then the outermost xeme cannot `success` as true, though it can be explicitly
100
- false.
248
+ No standards are defined on how promises should provide such information. A
249
+ substandard may be defined down the road.
250
+
251
+ Best practice is that when a promise xeme is supplanted, it should have a nested
252
+ xeme that provides the final success/failure of the process.
253
+
254
+ ```json
255
+ {
256
+ "success": true,
257
+ "supplanted": true,
258
+ "type":"promise",
259
+ "uri": "https://example.com/20435t",
260
+ "delay": 6000,
261
+
262
+ "nested": [
263
+ {"success":true}
264
+ ]
265
+ }
266
+ ```
101
267
 
102
268
  ## Xeme gem
103
269
 
@@ -105,8 +271,8 @@ false.
105
271
 
106
272
  The usual:
107
273
 
108
- ```sh
109
- gem install xeme
274
+ ```bash
275
+ sudo gem install xeme
110
276
  ```
111
277
 
112
278
  ### Basic Xeme concepts
@@ -122,14 +288,6 @@ xeme = Xeme.new
122
288
  puts xeme # => #<Xeme:0x000055586f1340a8>
123
289
  ```
124
290
 
125
- Sometimes it's handy to give a xeme an identifier. You can do that by passing in
126
- a string in `Xeme.new`.
127
-
128
- ```ruby
129
- xeme = Xeme.new('my-xeme')
130
- puts xeme.id # => my-xeme
131
- ```
132
-
133
291
  If you want to access the hash stored in the xeme object, you can use the object
134
292
  as if it were a hash.
135
293
 
@@ -141,36 +299,30 @@ xeme['errors'].push({'id'=>'my-error'})
141
299
  ### Success and failure
142
300
 
143
301
  Because a xeme isn't considered successful until it has been explicitly declared
144
- so, a new xeme is considered to indicate failure. However, because there are no
145
- errors and `success` has not been explicitly set, `success?` returns `nil`
146
- instead of `false`.
302
+ so, a new xeme is considered to indicate failure or lack of determination of
303
+ success/failure.
147
304
 
148
305
  ```ruby
149
306
  xeme = Xeme.new
150
307
  puts xeme.success?.class # => NilClas
151
308
  ```
152
309
 
153
- There are two ways to mark a xeme as successful, one of which usually the better
154
- choice. The not-so-good way to mark success is with the `succeed` method.
310
+ To set a xeme to indicate failure, use the `fail` method.
155
311
 
156
312
  ```ruby
157
313
  xeme = Xeme.new
158
- xeme.succeed
159
- puts xeme.success? # => true
314
+ xeme.fail
315
+ puts xeme.success? # => false
160
316
  ```
161
317
 
162
- The problem with `succeed` is that if there are errors, `succeed` will raise an
163
- exception.
318
+ Perhaps counter-intuitively, there is no `succeed` method. That's because a xeme
319
+ cannot be reliably marked as succeeding without checking nested xemes (see
320
+ [resolution](#resolution)).
164
321
 
165
- ```ruby
166
- xeme = Xeme.new
167
- xeme.error 'my-error'
168
- xeme.succeed # => raises exception: `succeed': cannot-set-to-success: errors
169
- ```
170
-
171
- A better option is `try_succeed`. If your script gets to a point, usually at the
172
- end of the function or script, that you want to set the xeme to success, but
173
- only if there are no errors, use `try_succeed`.
322
+ Instead there is a `try_succeed` method. As its name implies, that method
323
+ resolves the xeme and its descendents, only marking the xeme as successful if
324
+ resolution allows. We'll get more into handling nested xemes later. The
325
+ following example shows setting a single xeme to success using `try_succeed`.
174
326
 
175
327
  ```ruby
176
328
  xeme = Xeme.new
@@ -178,217 +330,144 @@ xeme.try_succeed
178
330
  puts xeme.success? # => true
179
331
  ```
180
332
 
181
- If there are errors, `try_succeed` won't raise an exception, but will not set
182
- the xeme to failure.
333
+ `try_succeed` will only set a xeme to success if the current success is null or
334
+ true. It will not override an explicit setting of false.
183
335
 
184
336
  ```ruby
185
337
  xeme = Xeme.new
186
- xeme.error 'my-error'
338
+ xeme.fail
187
339
  xeme.try_succeed
188
340
  puts xeme.success? # => false
189
341
  ```
190
342
 
191
- ### Creating and using messages
343
+ ### Nesting xemes
192
344
 
193
- Messages in a xeme provide a way to indicate errors (i.e. fatal errors),
194
- warnings (non-fatal errors), notes (not an error at all), and promises (guides
195
- to getting the final success or failure of the process). A message is a hash
196
- with whatever arbitrary information you want to add. Each type of message has
197
- its own method for creating it, an array for storing them, and methods for
198
- checking if any exist. The following script creates an error, a warning, a
199
- note, and a promise.
345
+ Use `nest` to create nested xemes. If a block is sent, `nest` yields the new
346
+ xeme.
200
347
 
201
348
  ```ruby
202
- xeme = Xeme.new
203
- xeme.error 'my-error'
204
- xeme.warning 'my-warning'
205
- xeme.note 'my-note'
206
- xeme.promise 'my-promise'
349
+ xeme.nest() do |child|
350
+ # do stuff with nested xeme
351
+ end
207
352
  ```
208
353
 
209
- `#error`, `#warning`, `#note`, and `#promise` each create a message for their
210
- own type. Although it is not required, it's usually a good idea to give a string
211
- as the first parameter. That string will be set to the `id` element in the
212
- resulting hash, as seen in the example above.
354
+ `nest` also returns the new xeme.
355
+
356
+ ```ruby
357
+ child = xeme.nest()
358
+ ```
213
359
 
214
- `#errors`, `#warnings`, `#notes`, and `#promises` return arrays for each type.
360
+ Several methods exist to provide shortcuts for creating nested xemes of various
361
+ types: `success`, `error`, `warning`, `note`, and `promise`.
215
362
 
216
363
  ```ruby
217
- xeme.errors.each do |e|
218
- puts e['id'] # => my-error
364
+ xeme.success() do |child|
365
+ puts child.success? # => true
219
366
  end
220
367
 
221
- xeme.warnings.each do |w|
222
- puts w['id'] # => my-warning
368
+ xeme.error() do |child|
369
+ puts child.success? # => false
223
370
  end
224
371
 
225
- xeme.notes.each do |n|
226
- puts n['id'] # => my-note
372
+ # Xeme#failure does same thing as Xeme#error
373
+ xeme.failure() do |child|
374
+ puts child.success? # => false
227
375
  end
228
376
 
229
- xeme.promises.each do |p|
230
- puts p['id'] # => my-promise
377
+ xeme.warning() do |child|
378
+ puts child.class # => Xeme::Warning
231
379
  end
232
- ```
233
-
234
- **Gotcha:** These methods return frozen arrays, *not* the arrays in the xeme.
235
- This is because these methods return not only the xeme's own message arrays, but
236
- also any nested messages. See [Nesting xemes](#nesting-xemes) below.
237
-
238
- There are several ways to create and populate a message. Choose whichever is
239
- preferable to you. One way is demonstrated in the example above. You simply call
240
- the appropriate method, passing in an identifier. If all you want to do is
241
- create a message with an `id` then that's probably the easiest choice.
242
-
243
- Another way to use a `do` block to add custom information to the message.
244
380
 
245
- ```ruby
246
- xeme.error('my-error') do |error|
247
- error['database-error'] = 'some database error'
248
- error['commands'] = ['a', 'b', 'c']
381
+ xeme.note() do |child|
382
+ puts child.class # => Xeme::Note
249
383
  end
250
- ```
251
-
252
- Remember a message is just a hash, so you can add any kind of structure to the
253
- hash you want such a strings, booleans, hashes, and arrays.
254
-
255
- Finally, the message command returns the new message. So, if you want, you can
256
- assign that return value to a variable and work with the message that way.
257
-
258
- ```ruby
259
- err = xeme.error('my-error')
260
- err['database-error'] = 'some database error'
261
- err['commands'] = ['a', 'b', 'c']
262
- ```
263
-
264
- ### Creating metainformation
265
-
266
- The `#meta` method returns the `meta` element in the xeme hash, creating it if
267
- necessary. The hash will be automatically populated with a timestamp and a UUID.
268
- If you gave the xeme an identifier when you created it, that id will stored in
269
- the meta hash:
270
384
 
271
- ```ruby
272
- xeme = Xeme.new('my-xeme')
273
- puts xeme.meta
274
- ```
275
-
276
- This produces a `meta` hash like this:
277
-
278
- ```ruby
279
- {
280
- "uuid"=>"4e736a8f-314e-470a-8209-6811a7b2d38c",
281
- "timestamp"=>2023-05-29 19:22:37.26152866 -0400,
282
- "id"=>"my-xeme"
283
- }
284
- ```
285
-
286
- If you don't pass in an id then the meta hash isn't created. However, you can
287
- always create and use the meta hash by calling the `#meta` method. The timestamp
288
- and UUID will be automatically created.
289
-
290
- ```ruby
291
- xeme = Xeme.new
292
- xeme.meta['foo'] = 'bar'
293
- xeme.meta.class # => Hash
385
+ xeme.promise() do |child|
386
+ puts child.class # => Xeme::Promise
387
+ end
294
388
  ```
295
389
 
296
- ### Nesting xemes
297
-
298
- In complex testing situations it can be useful to nest results within other
299
- results. To nest a xeme within another xeme, use the `#nest` method:
300
-
301
- ```ruby
302
- xeme = Xeme.new('results')
303
- xeme.nest 'child-xeme'
304
- ```
390
+ #### Querying nested xemes
305
391
 
306
- You probably want to do something more than just create a nested xeme, so you
307
- can use a `do` block to work with the nested xeme:
392
+ Xeme provides several methods for traversing through a stack of nested xemes. In
393
+ the following examples, we'll use this structure:
308
394
 
309
395
  ```ruby
310
- xeme.nest('child-xeme') do |child|
311
- child.error 'child-error'
396
+ xeme = Xeme.new()
397
+ xeme.id = 'top'
398
+
399
+ xeme.nest() do |child|
400
+ child.id = 'foo'
401
+
402
+ child.nest() do |grandchild|
403
+ grandchild.id = 'bar'
404
+ grandchild.warning.id = 'my-warning'
405
+ grandchild.promise.id = 'my-promise'
406
+ grandchild.success
407
+ end
408
+
409
+ child.error.id = 'my-error'
410
+ child.note.id = 'my-note'
312
411
  end
313
412
  ```
314
413
 
315
- You can loop through all xemes, including the outermost xeme and all nested
316
- xemes, using the `#all` method.
414
+ The simplest is the `all` method, which returns the xeme itself and all nested
415
+ xemes as a locked array.
317
416
 
318
417
  ```ruby
319
418
  xeme.all.each do |x|
320
419
  puts x.id
321
420
  end
322
- ```
323
421
 
324
- **Nested messages**
422
+ # => top
423
+ # => foo
424
+ # => bar
425
+ # => my-warning
426
+ # => my-promise
427
+ # => my-error
428
+ # => my-note
429
+ ```
325
430
 
326
- The `#errors`, `#warnings`, `#notes`, and `#promises` methods return arrays of
327
- all messages within the xeme, including the outermost xeme and nested xemes.
431
+ There are several methods for selecting xemes based on their success status.
328
432
 
329
433
  ```ruby
330
- xeme = Xeme.new
331
- xeme.error 'outer-error'
332
-
333
- xeme.nest do |child|
334
- child.error 'child-error'
335
- end
434
+ # xemes marked as success=false
435
+ puts xeme.errors.length # => 3
336
436
 
337
- puts xeme.errors
437
+ # xemes marked as success=true
438
+ puts xeme.successes.length # => 1
338
439
 
339
- # => {"id"=>"outer-error"}
340
- # => {"id"=>"child-error"}
440
+ # xemes marked as success=null
441
+ # does not return advisory xemes
442
+ puts xeme.nils.length # => 2
341
443
  ```
342
444
 
343
- If you want to search for messages with a specific `id`, add that id to the
344
- messages method:
445
+ There are also several methods for selecting specific xemes based on their types.
345
446
 
346
447
  ```ruby
347
- puts xeme.errors('child-error') # => {"id"=>"child-error"}
448
+ puts xeme.warnings.length # => 1
449
+ puts xeme.notes.length # => 2
450
+ puts xeme.promises.length # => 1
348
451
  ```
349
452
 
350
- **Flatten**
453
+ ### resolve() and try_succeed()
351
454
 
352
- Finally, if you want to slurp up all messages into the outermost xeme and delete
353
- the nested xemes, use `#flatten`.
455
+ Xemes can be [resolved](#resolution) using the `resolve` method.
354
456
 
355
457
  ```ruby
356
- puts xeme['errors']
357
- # => {"id"=>"outer-error"}
358
-
359
- xeme.flatten
360
-
361
- puts xeme['errors']
362
- # => {"id"=>"outer-error"}
363
- # => {"id"=>"child-error"}
458
+ xeme.resolve
364
459
  ```
365
460
 
461
+ It's common that your process will get to a point, typically at the end of the
462
+ script, where you want to mark the process as successful, but only if there were
463
+ no errors. Use `try_succeed` for that. That method first resolves the xeme and
464
+ its descendents, then marks the xeme (and descendents) as successful if there
465
+ are no errors.
366
466
 
367
- ### Resolving xemes
368
-
369
- A xeme can contain contradictory information. For example, if `success` is true
370
- but there are errors, then the xeme should be considered as failed. If there are
371
- promises, then the xeme should not be considered as failed, although `success`
372
- may be set as nil.
373
-
374
- The `#resolve` method resolves those contradictions. Generally you won't have to
375
- call `#resolve` yourself, but it's worth understanding the rules:
376
-
377
- * A xeme can always be explicitly set to false, regardless of any other
378
- considerations. Resolution never changes a `success` of false.
379
-
380
- * If any nested xemes have `success` explicitly set to false, then the outermost
381
- xeme will be set to false.
382
-
383
- * If a xeme has errors, or any of its nested xemes has errors, then it is set to
384
- false.
385
-
386
- * If a xeme has promises, or any of its nested xemes do, then it cannot be set
387
- to true. If it is already false, then it stays false. Otherwise `success` is set
388
- to nil.
389
-
390
- * If any nested xemes have `success` set to nil, then the outermost xeme cannot
391
- be set to true.
467
+ ```ruby
468
+ xeme.try_succeed
469
+ puts xeme.success? # => true, false, or nil
470
+ ```
392
471
 
393
472
  ## The name
394
473
 
@@ -409,4 +488,6 @@ mike@idocs.com
409
488
  |---------|--------------|-------------------------------|
410
489
  | 0.1 | Jan 7, 2020 | Initial upload. |
411
490
  | 1.0 | May 29, 2023 | Complete overhaul. Not backward compatible. |
412
- | 1.1 | May 29, 2023 | Added and cleaned up documentation. No change to funcationality. |
491
+ | 1.1 | May 29, 2023 | Added and cleaned up documentation. No change to functionality. |
492
+ | 1.2 | May 29, 2023 | More cleanup to documentation. |
493
+ | 2.0 | Jun 22, 2023 | Another complete overhaul. This should be the last non-backwards compatible revision. |