xeme 1.2 → 2.0
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/README.md +306 -225
- data/lib/xeme.rb +694 -627
- metadata +25 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae47399bb72561b8d7d6efedeb37e43840269d5fb6ab686bdfc31499ee3595e8
|
4
|
+
data.tar.gz: 83c15744b30011cfd1cac0ee53771ee790f34a15b5983af1763b65000109bc64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
23
|
-
|
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
|
-
|
39
|
-
should be considered to
|
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
|
-
|
41
|
+
```json
|
42
|
+
{"success":{}}
|
43
|
+
```
|
44
44
|
|
45
|
-
A
|
46
|
-
|
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
|
-
{
|
49
|
+
{"success":true, "tags":["a", "b"]}
|
50
50
|
```
|
51
51
|
|
52
|
-
|
53
|
-
to give each message an identifier (`id`).
|
52
|
+
### Metainformation
|
54
53
|
|
55
|
-
|
56
|
-
|
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
|
-
|
61
|
-
|
62
|
-
|
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
|
-
|
65
|
-
|
68
|
+
`meta` can contain any arbitrary information you want, but several elements, if
|
69
|
+
present, should follow some standards.
|
66
70
|
|
67
|
-
|
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
|
-
|
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
|
-
|
76
|
-
|
77
|
-
|
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
|
-
|
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
|
-
|
85
|
-
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
]
|
242
|
+
"type":"promise",
|
243
|
+
"uri": "https://example.com/20435t",
|
244
|
+
"delay": 6000
|
93
245
|
}
|
94
246
|
```
|
95
247
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
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
|
-
```
|
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
|
145
|
-
|
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
|
-
|
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.
|
159
|
-
puts xeme.success?
|
314
|
+
xeme.fail
|
315
|
+
puts xeme.success? # => false
|
160
316
|
```
|
161
317
|
|
162
|
-
|
163
|
-
|
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
|
-
|
166
|
-
xeme
|
167
|
-
|
168
|
-
|
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
|
-
|
182
|
-
|
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.
|
338
|
+
xeme.fail
|
187
339
|
xeme.try_succeed
|
188
340
|
puts xeme.success? # => false
|
189
341
|
```
|
190
342
|
|
191
|
-
###
|
343
|
+
### Nesting xemes
|
192
344
|
|
193
|
-
|
194
|
-
|
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
|
203
|
-
xeme
|
204
|
-
|
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
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
354
|
+
`nest` also returns the new xeme.
|
355
|
+
|
356
|
+
```ruby
|
357
|
+
child = xeme.nest()
|
358
|
+
```
|
213
359
|
|
214
|
-
|
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.
|
218
|
-
|
364
|
+
xeme.success() do |child|
|
365
|
+
puts child.success? # => true
|
219
366
|
end
|
220
367
|
|
221
|
-
xeme.
|
222
|
-
|
368
|
+
xeme.error() do |child|
|
369
|
+
puts child.success? # => false
|
223
370
|
end
|
224
371
|
|
225
|
-
|
226
|
-
|
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.
|
230
|
-
|
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
|
-
|
246
|
-
|
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
|
-
|
272
|
-
|
273
|
-
|
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
|
-
|
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
|
-
|
307
|
-
|
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.
|
311
|
-
|
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
|
-
|
316
|
-
xemes
|
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
|
-
|
422
|
+
# => top
|
423
|
+
# => foo
|
424
|
+
# => bar
|
425
|
+
# => my-warning
|
426
|
+
# => my-promise
|
427
|
+
# => my-error
|
428
|
+
# => my-note
|
429
|
+
```
|
325
430
|
|
326
|
-
|
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
|
-
|
331
|
-
xeme.
|
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
|
-
|
437
|
+
# xemes marked as success=true
|
438
|
+
puts xeme.successes.length # => 1
|
338
439
|
|
339
|
-
#
|
340
|
-
#
|
440
|
+
# xemes marked as success=null
|
441
|
+
# does not return advisory xemes
|
442
|
+
puts xeme.nils.length # => 2
|
341
443
|
```
|
342
444
|
|
343
|
-
|
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.
|
448
|
+
puts xeme.warnings.length # => 1
|
449
|
+
puts xeme.notes.length # => 2
|
450
|
+
puts xeme.promises.length # => 1
|
348
451
|
```
|
349
452
|
|
350
|
-
|
453
|
+
### resolve() and try_succeed()
|
351
454
|
|
352
|
-
|
353
|
-
the nested xemes, use `#flatten`.
|
455
|
+
Xemes can be [resolved](#resolution) using the `resolve` method.
|
354
456
|
|
355
457
|
```ruby
|
356
|
-
|
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
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
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
|
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. |
|