functional-light-service 0.5.4 → 6.0.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/.github/workflows/project-build.yml +35 -11
- data/.rubocop.yml +101 -160
- data/AUDIT-functional-light-service.md +352 -0
- data/CHANGELOG.md +38 -0
- data/README.md +54 -2
- data/audit/bench.rb +99 -0
- data/audit/verify_findings.rb +172 -0
- data/functional-light-service.gemspec +15 -21
- data/lib/functional-light-service/action.rb +97 -101
- data/lib/functional-light-service/configuration.rb +26 -24
- data/lib/functional-light-service/context/key_verifier.rb +124 -118
- data/lib/functional-light-service/context.rb +63 -20
- data/lib/functional-light-service/deprecations.rb +26 -0
- data/lib/functional-light-service/errors.rb +8 -6
- data/lib/functional-light-service/functional/enum.rb +286 -250
- data/lib/functional-light-service/functional/maybe.rb +21 -15
- data/lib/functional-light-service/functional/monad.rb +77 -66
- data/lib/functional-light-service/functional/null.rb +88 -74
- data/lib/functional-light-service/functional/option.rb +100 -97
- data/lib/functional-light-service/functional/result.rb +129 -116
- data/lib/functional-light-service/localization_adapter.rb +48 -47
- data/lib/functional-light-service/organizer/execute.rb +16 -14
- data/lib/functional-light-service/organizer/iterate.rb +30 -25
- data/lib/functional-light-service/organizer/reduce_if.rb +19 -17
- data/lib/functional-light-service/organizer/reduce_until.rb +22 -20
- data/lib/functional-light-service/organizer/scoped_reducable.rb +15 -13
- data/lib/functional-light-service/organizer/with_callback.rb +28 -26
- data/lib/functional-light-service/organizer/with_reducer.rb +81 -77
- data/lib/functional-light-service/organizer/with_reducer_factory.rb +20 -18
- data/lib/functional-light-service/organizer/with_reducer_log_decorator.rb +110 -108
- data/lib/functional-light-service/organizer.rb +114 -114
- data/lib/functional-light-service/testing/context_factory.rb +48 -42
- data/lib/functional-light-service/testing.rb +3 -1
- data/lib/functional-light-service/version.rb +5 -3
- data/lib/functional-light-service.rb +30 -28
- data/spec/acceptance/after_actions_spec.rb +87 -71
- data/spec/acceptance/before_actions_spec.rb +115 -98
- data/spec/acceptance/custom_log_from_organizer_spec.rb +61 -60
- data/spec/acceptance/deprecation_warnings_spec.rb +82 -0
- data/spec/acceptance/fail_spec.rb +52 -50
- data/spec/acceptance/message_localization_spec.rb +119 -118
- data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +68 -65
- data/spec/acceptance/organizer/reduce_if_spec.rb +89 -89
- data/spec/acceptance/organizer/with_callback_spec.rb +113 -110
- data/spec/acceptance/{not_having_call_method_warning_spec.rb → organizer_entry_point_spec.rb} +10 -7
- data/spec/acceptance/rollback_spec.rb +183 -132
- data/spec/action_expects_and_promises_spec.rb +97 -93
- data/spec/action_promised_keys_spec.rb +126 -122
- data/spec/context_spec.rb +289 -197
- data/spec/examples/controller_spec.rb +63 -63
- data/spec/examples/validate_address_spec.rb +38 -37
- data/spec/lib/deterministic/currify_spec.rb +90 -88
- data/spec/lib/deterministic/null_spec.rb +6 -1
- data/spec/lib/deterministic/option_spec.rb +140 -137
- data/spec/lib/deterministic/result/result_map_spec.rb +155 -154
- data/spec/lib/deterministic/result/result_shared.rb +3 -2
- data/spec/lib/deterministic/result_spec.rb +2 -2
- data/spec/lib/edge_cases_spec.rb +156 -0
- data/spec/lib/enum_spec.rb +1 -1
- data/spec/lib/native_pattern_matching_spec.rb +74 -0
- data/spec/organizer_spec.rb +115 -114
- data/spec/readme_spec.rb +45 -47
- data/spec/sample/calculates_order_tax_action_spec.rb +16 -16
- data/spec/sample/calculates_tax_spec.rb +1 -1
- data/spec/sample/looks_up_tax_percentage_action_spec.rb +55 -55
- data/spec/sample/tax/calculates_order_tax_action.rb +10 -9
- data/spec/sample/tax/looks_up_tax_percentage_action.rb +28 -27
- data/spec/sample/tax/provides_free_shipping_action.rb +11 -10
- data/spec/spec_helper.rb +6 -0
- data/spec/test_doubles.rb +628 -599
- data/spec/testing/context_factory_spec.rb +21 -0
- metadata +45 -161
- data/lib/functional-light-service/organizer/verify_call_method_exists.rb +0 -29
- data/spec/acceptance/include_warning_spec.rb +0 -29
data/spec/test_doubles.rb
CHANGED
|
@@ -1,599 +1,628 @@
|
|
|
1
|
-
# A collection of Action and Organizer dummies used in specs
|
|
2
|
-
|
|
3
|
-
module TestDoubles
|
|
4
|
-
class RollbackAction
|
|
5
|
-
extend FunctionalLightService::Action
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def self.call(
|
|
42
|
-
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
class
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
def self.
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
def
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
end
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
class
|
|
289
|
-
extend FunctionalLightService::
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
expects :tea
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
expects :tea
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
end
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
ctx.counter =
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
end
|
|
1
|
+
# A collection of Action and Organizer dummies used in specs
|
|
2
|
+
|
|
3
|
+
module TestDoubles
|
|
4
|
+
class RollbackAction
|
|
5
|
+
extend FunctionalLightService::Action
|
|
6
|
+
|
|
7
|
+
executed(&:fail_with_rollback!)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class RaiseErrorAction
|
|
11
|
+
extend FunctionalLightService::Action
|
|
12
|
+
|
|
13
|
+
executed do |_ctx|
|
|
14
|
+
raise 'A problem has occured.'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class RaiseAnotherErrorAction
|
|
19
|
+
extend FunctionalLightService::Action
|
|
20
|
+
|
|
21
|
+
executed do |_ctx|
|
|
22
|
+
raise 'More problems'
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class SkipAllAction
|
|
27
|
+
extend FunctionalLightService::Action
|
|
28
|
+
|
|
29
|
+
executed(&:skip_remaining!)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class FailureAction
|
|
33
|
+
extend FunctionalLightService::Action
|
|
34
|
+
|
|
35
|
+
executed(&:fail!)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class AddTwoOrganizer
|
|
39
|
+
extend FunctionalLightService::Organizer
|
|
40
|
+
|
|
41
|
+
def self.call(context)
|
|
42
|
+
with(context).reduce([AddsOneAction, AddsOneAction])
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class AroundEachNullHandler
|
|
47
|
+
def self.call(_action)
|
|
48
|
+
yield
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class TestLogger
|
|
53
|
+
attr_accessor :logs
|
|
54
|
+
|
|
55
|
+
def initialize
|
|
56
|
+
@logs = []
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class AroundEachLoggerHandler
|
|
61
|
+
def self.call(context)
|
|
62
|
+
before_number = context[:number]
|
|
63
|
+
result = yield
|
|
64
|
+
|
|
65
|
+
context[:logger].logs << {
|
|
66
|
+
:action => context.current_action,
|
|
67
|
+
:before => before_number,
|
|
68
|
+
:after => result[:number]
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
result
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
class AroundEachOrganizer
|
|
76
|
+
extend FunctionalLightService::Organizer
|
|
77
|
+
|
|
78
|
+
def self.call(action_arguments)
|
|
79
|
+
with(action_arguments)
|
|
80
|
+
.around_each(AroundEachLoggerHandler)
|
|
81
|
+
.reduce([AddsTwoActionWithFetch])
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
class AddsTwoActionWithFetch
|
|
86
|
+
extend FunctionalLightService::Action
|
|
87
|
+
|
|
88
|
+
executed do |context|
|
|
89
|
+
number = context.fetch(:number, 0)
|
|
90
|
+
context[:number] = number + 2
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class AnAction
|
|
95
|
+
extend FunctionalLightService::Action
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class AnotherAction
|
|
99
|
+
extend FunctionalLightService::Action
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
class AnOrganizer
|
|
103
|
+
extend FunctionalLightService::Organizer
|
|
104
|
+
|
|
105
|
+
def self.call(action_arguments)
|
|
106
|
+
with(action_arguments).reduce([AnAction, AnotherAction])
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def self.do_something_with_no_actions(action_arguments)
|
|
110
|
+
with(action_arguments).reduce
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def self.do_something_with_no_starting_context
|
|
114
|
+
reduce([AnAction, AnotherAction])
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
class NotExplicitlyReturningContextOrganizer
|
|
119
|
+
extend FunctionalLightService::Organizer
|
|
120
|
+
|
|
121
|
+
def self.call(context)
|
|
122
|
+
context[:foo] = [1, 2, 3]
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
class NestingOrganizer
|
|
127
|
+
extend FunctionalLightService::Organizer
|
|
128
|
+
|
|
129
|
+
def self.call(context)
|
|
130
|
+
with(context).reduce(actions)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def self.actions
|
|
134
|
+
[NotExplicitlyReturningContextOrganizer, NestedAction]
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
class NestedAction
|
|
139
|
+
extend FunctionalLightService::Action
|
|
140
|
+
|
|
141
|
+
expects :foo
|
|
142
|
+
|
|
143
|
+
executed do |context|
|
|
144
|
+
context[:bar] = context.foo
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
class MakesTeaWithMilkAction
|
|
149
|
+
extend FunctionalLightService::Action
|
|
150
|
+
|
|
151
|
+
expects :tea, :milk
|
|
152
|
+
promises :milk_tea
|
|
153
|
+
|
|
154
|
+
executed do |context|
|
|
155
|
+
context.milk_tea = "#{context.tea} - #{context.milk}"
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
class MultipleExpectsAction
|
|
160
|
+
extend FunctionalLightService::Action
|
|
161
|
+
|
|
162
|
+
expects :tea
|
|
163
|
+
expects :milk, :chocolate
|
|
164
|
+
promises :milk_tea
|
|
165
|
+
|
|
166
|
+
executed do |context|
|
|
167
|
+
context.milk_tea = "#{context.tea} - #{context.milk} " \
|
|
168
|
+
"- with #{context.chocolate}"
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
class MakesCappuccinoAction
|
|
173
|
+
extend FunctionalLightService::Action
|
|
174
|
+
|
|
175
|
+
expects :coffee, :milk
|
|
176
|
+
promises :cappuccino
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
class MakesLatteAction
|
|
180
|
+
extend FunctionalLightService::Action
|
|
181
|
+
|
|
182
|
+
expects :coffee, :milk
|
|
183
|
+
promises :latte
|
|
184
|
+
|
|
185
|
+
executed do |context|
|
|
186
|
+
context.fail!("Can't make a latte from a milk that's very hot!") if context.milk == :very_hot
|
|
187
|
+
|
|
188
|
+
if context.milk == :super_hot
|
|
189
|
+
error_message = "Can't make a latte from a milk that's super hot!"
|
|
190
|
+
context.fail_with_rollback!(error_message)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
context[:latte] = "#{context.coffee} - with lots of #{context.milk}"
|
|
194
|
+
|
|
195
|
+
if context.milk == "5%"
|
|
196
|
+
msg = "Can't make a latte with a fatty milk like that!"
|
|
197
|
+
context.skip_remaining!(msg)
|
|
198
|
+
next context
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
class MultiplePromisesAction
|
|
204
|
+
extend FunctionalLightService::Action
|
|
205
|
+
|
|
206
|
+
expects :coffee, :milk
|
|
207
|
+
promises :cappuccino
|
|
208
|
+
promises :latte
|
|
209
|
+
|
|
210
|
+
executed do |context|
|
|
211
|
+
context.cappuccino = "Cappucino needs #{context.coffee} and a little milk"
|
|
212
|
+
context.latte = "Latte needs #{context.coffee} and a lot of milk"
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
class MakesTeaAndCappuccino
|
|
217
|
+
extend FunctionalLightService::Organizer
|
|
218
|
+
|
|
219
|
+
def self.call(tea, milk, coffee)
|
|
220
|
+
with(:tea => tea, :milk => milk, :coffee => coffee)
|
|
221
|
+
.reduce(TestDoubles::MakesTeaWithMilkAction,
|
|
222
|
+
TestDoubles::MakesLatteAction)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
class MakesCappuccinoAddsTwo
|
|
227
|
+
extend FunctionalLightService::Organizer
|
|
228
|
+
|
|
229
|
+
def self.call(milk, coffee)
|
|
230
|
+
with(:milk => milk, :coffee => coffee)
|
|
231
|
+
.reduce(TestDoubles::AddsTwoActionWithFetch,
|
|
232
|
+
TestDoubles::MakesLatteAction)
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
class MakesCappuccinoAddsTwoAndFails
|
|
237
|
+
extend FunctionalLightService::Organizer
|
|
238
|
+
|
|
239
|
+
def self.call(coffee, this_hot = :very_hot)
|
|
240
|
+
with(:milk => this_hot, :coffee => coffee)
|
|
241
|
+
.reduce(TestDoubles::MakesLatteAction,
|
|
242
|
+
TestDoubles::AddsTwoActionWithFetch)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
class MakesCappuccinoSkipsAddsTwo
|
|
247
|
+
extend FunctionalLightService::Organizer
|
|
248
|
+
|
|
249
|
+
def self.call(coffee)
|
|
250
|
+
with(:milk => "5%", :coffee => coffee)
|
|
251
|
+
.reduce(TestDoubles::MakesLatteAction,
|
|
252
|
+
TestDoubles::AddsTwoActionWithFetch)
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
class AdditionOrganizer
|
|
257
|
+
extend FunctionalLightService::Organizer
|
|
258
|
+
|
|
259
|
+
def self.call(number)
|
|
260
|
+
with(:number => number).reduce(actions)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def self.actions
|
|
264
|
+
[
|
|
265
|
+
AddsOneAction,
|
|
266
|
+
AddsTwoAction,
|
|
267
|
+
AddsThreeAction
|
|
268
|
+
]
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
class ExtraArgumentAdditionOrganizer
|
|
273
|
+
extend FunctionalLightService::Organizer
|
|
274
|
+
|
|
275
|
+
def self.call(number, another_number)
|
|
276
|
+
with(:number => number + another_number).reduce(actions)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def self.actions
|
|
280
|
+
[
|
|
281
|
+
AddsOneAction,
|
|
282
|
+
AddsTwoAction,
|
|
283
|
+
AddsThreeAction
|
|
284
|
+
]
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
class AddsOne
|
|
289
|
+
extend FunctionalLightService::Organizer
|
|
290
|
+
|
|
291
|
+
def call(ctx)
|
|
292
|
+
with(ctx).reduce(actions)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def self.actions
|
|
296
|
+
[AddsOneAction]
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
class AddsOneAction
|
|
301
|
+
extend FunctionalLightService::Action
|
|
302
|
+
|
|
303
|
+
expects :number
|
|
304
|
+
promises :number
|
|
305
|
+
|
|
306
|
+
executed do |context|
|
|
307
|
+
context.number += 1
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
class AddsTwoAction
|
|
312
|
+
extend FunctionalLightService::Action
|
|
313
|
+
|
|
314
|
+
expects :number
|
|
315
|
+
|
|
316
|
+
executed do |context|
|
|
317
|
+
context.number += 2
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
class AddsThreeAction
|
|
322
|
+
extend FunctionalLightService::Action
|
|
323
|
+
|
|
324
|
+
expects :number
|
|
325
|
+
|
|
326
|
+
executed do |context|
|
|
327
|
+
context.number += 3
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
class IterateOrganizer
|
|
332
|
+
extend FunctionalLightService::Organizer
|
|
333
|
+
|
|
334
|
+
def self.call(ctx)
|
|
335
|
+
with(ctx).reduce(actions)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def self.actions
|
|
339
|
+
[
|
|
340
|
+
AddsOneIteratesAction,
|
|
341
|
+
iterate(:numbers, [
|
|
342
|
+
AddsTwoAction,
|
|
343
|
+
AddsThreeAction
|
|
344
|
+
])
|
|
345
|
+
]
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
class AddsOneIteratesAction
|
|
350
|
+
extend FunctionalLightService::Action
|
|
351
|
+
|
|
352
|
+
expects :numbers
|
|
353
|
+
promises :numbers
|
|
354
|
+
|
|
355
|
+
executed do |context|
|
|
356
|
+
context.numbers = context.numbers.map { |n| n + 1 }
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
class CallbackOrganizer
|
|
361
|
+
extend FunctionalLightService::Organizer
|
|
362
|
+
|
|
363
|
+
def self.call(ctx)
|
|
364
|
+
with(ctx).reduce(actions)
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def self.actions
|
|
368
|
+
[
|
|
369
|
+
AddsOneAction,
|
|
370
|
+
with_callback(AddTenCallbackAction, [
|
|
371
|
+
AddsTwoAction,
|
|
372
|
+
AddsThreeAction
|
|
373
|
+
])
|
|
374
|
+
]
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
class AddTenCallbackAction
|
|
379
|
+
extend FunctionalLightService::Action
|
|
380
|
+
|
|
381
|
+
expects :number, :callback
|
|
382
|
+
|
|
383
|
+
executed do |context|
|
|
384
|
+
context.number += 10
|
|
385
|
+
context.number =
|
|
386
|
+
context.callback.call(context).fetch(:number)
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
class ReduceUntilOrganizer
|
|
391
|
+
extend FunctionalLightService::Organizer
|
|
392
|
+
|
|
393
|
+
def self.call(ctx)
|
|
394
|
+
with(ctx).reduce(actions)
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def self.actions
|
|
398
|
+
[
|
|
399
|
+
AddsOneAction,
|
|
400
|
+
reduce_until(->(ctx) { ctx.number > 3 }, [
|
|
401
|
+
AddsTwoAction,
|
|
402
|
+
AddsThreeAction
|
|
403
|
+
])
|
|
404
|
+
]
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
class ReduceIfOrganizer
|
|
409
|
+
extend FunctionalLightService::Organizer
|
|
410
|
+
|
|
411
|
+
def self.call(ctx)
|
|
412
|
+
with(ctx).reduce(actions)
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
def self.actions
|
|
416
|
+
[
|
|
417
|
+
AddsOneAction,
|
|
418
|
+
reduce_if(->(ctx) { ctx.number > 1 }, [
|
|
419
|
+
AddsTwoAction,
|
|
420
|
+
AddsThreeAction
|
|
421
|
+
])
|
|
422
|
+
]
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
class MakesTeaExpectingReservedKey
|
|
427
|
+
extend FunctionalLightService::Action
|
|
428
|
+
|
|
429
|
+
expects :tea, :message
|
|
430
|
+
|
|
431
|
+
executed do |context|
|
|
432
|
+
context.product = context.number + 3
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
class MakesTeaExpectingMultipleReservedKeys
|
|
437
|
+
extend FunctionalLightService::Action
|
|
438
|
+
|
|
439
|
+
expects :tea, :message, :error_code, :current_action
|
|
440
|
+
|
|
441
|
+
executed do |context|
|
|
442
|
+
context.product = context.number + 3
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
class MakesTeaPromisingReservedKey
|
|
447
|
+
extend FunctionalLightService::Action
|
|
448
|
+
|
|
449
|
+
expects :tea
|
|
450
|
+
promises :product, :message
|
|
451
|
+
|
|
452
|
+
executed do |context|
|
|
453
|
+
context.product = context.number + 3
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
class MakesTeaPromisingMultipleReservedKeys
|
|
458
|
+
extend FunctionalLightService::Action
|
|
459
|
+
|
|
460
|
+
expects :tea
|
|
461
|
+
promises :product, :message, :error_code, :current_action
|
|
462
|
+
|
|
463
|
+
executed do |context|
|
|
464
|
+
context.product = context.number + 3
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
class MakesTeaPromisingKeyButRaisesException
|
|
469
|
+
extend FunctionalLightService::Action
|
|
470
|
+
|
|
471
|
+
promises :product
|
|
472
|
+
|
|
473
|
+
executed do |context|
|
|
474
|
+
context.product = make_product
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
def self.make_product
|
|
478
|
+
raise "Fail"
|
|
479
|
+
end
|
|
480
|
+
private_class_method :make_product
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
class PromisesPromisedKeyAction
|
|
484
|
+
extend FunctionalLightService::Action
|
|
485
|
+
|
|
486
|
+
promises :promised_key
|
|
487
|
+
|
|
488
|
+
executed do |ctx|
|
|
489
|
+
ctx.promised_key = "promised_key"
|
|
490
|
+
end
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
class ExpectsExpectedKeyAction
|
|
494
|
+
extend FunctionalLightService::Action
|
|
495
|
+
|
|
496
|
+
expects :expected_key
|
|
497
|
+
promises :final_key
|
|
498
|
+
|
|
499
|
+
executed do |ctx|
|
|
500
|
+
ctx.final_key = ctx.expected_key
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
class NullAction
|
|
505
|
+
extend FunctionalLightService::Action
|
|
506
|
+
|
|
507
|
+
# rubocop:disable Lint/EmptyBlock
|
|
508
|
+
executed { |_ctx| }
|
|
509
|
+
# rubocop:enable Lint/EmptyBlock
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
class TestIterate
|
|
513
|
+
extend FunctionalLightService::Organizer
|
|
514
|
+
|
|
515
|
+
def self.call(context)
|
|
516
|
+
with(context)
|
|
517
|
+
.reduce([iterate(:counters,
|
|
518
|
+
[TestDoubles::AddsOneAction])])
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def self.call_single(context)
|
|
522
|
+
with(context)
|
|
523
|
+
.reduce([iterate(:counters,
|
|
524
|
+
TestDoubles::AddsOneAction)])
|
|
525
|
+
end
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
class TestWithCallback
|
|
529
|
+
extend FunctionalLightService::Organizer
|
|
530
|
+
|
|
531
|
+
def self.call(context = {})
|
|
532
|
+
with(context).reduce(actions)
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
def self.actions
|
|
536
|
+
[
|
|
537
|
+
SetUpContextAction,
|
|
538
|
+
with_callback(IterateCollectionAction,
|
|
539
|
+
[IncrementCountAction,
|
|
540
|
+
AddToTotalAction])
|
|
541
|
+
]
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
class SetUpContextAction
|
|
546
|
+
extend FunctionalLightService::Action
|
|
547
|
+
|
|
548
|
+
promises :numbers, :counter, :total
|
|
549
|
+
|
|
550
|
+
executed do |ctx|
|
|
551
|
+
ctx.numbers = [1, 2, 3]
|
|
552
|
+
ctx.counter = 0
|
|
553
|
+
ctx.total = 0
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
class IterateCollectionAction
|
|
558
|
+
extend FunctionalLightService::Action
|
|
559
|
+
|
|
560
|
+
expects :numbers, :callback
|
|
561
|
+
promises :number
|
|
562
|
+
|
|
563
|
+
executed do |ctx|
|
|
564
|
+
ctx.numbers.each do |number|
|
|
565
|
+
ctx.number = number
|
|
566
|
+
ctx.callback.call(ctx)
|
|
567
|
+
end
|
|
568
|
+
end
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
class IncrementCountAction
|
|
572
|
+
extend FunctionalLightService::Action
|
|
573
|
+
|
|
574
|
+
expects :counter
|
|
575
|
+
|
|
576
|
+
executed do |ctx|
|
|
577
|
+
ctx.counter = ctx.counter + 1
|
|
578
|
+
end
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
class AddToTotalAction
|
|
582
|
+
extend FunctionalLightService::Action
|
|
583
|
+
|
|
584
|
+
expects :number, :total
|
|
585
|
+
|
|
586
|
+
executed do |ctx|
|
|
587
|
+
ctx.total += ctx.number
|
|
588
|
+
end
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
class CapitalizeMessage
|
|
592
|
+
extend FunctionalLightService::Action
|
|
593
|
+
|
|
594
|
+
expects :a_message
|
|
595
|
+
promises :final_message
|
|
596
|
+
|
|
597
|
+
executed do |ctx|
|
|
598
|
+
ctx.final_message = ctx.a_message.upcase
|
|
599
|
+
end
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
class AnOrganizerThatAddsToContext
|
|
603
|
+
extend FunctionalLightService::Organizer
|
|
604
|
+
|
|
605
|
+
def self.call
|
|
606
|
+
with.reduce(actions)
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
def self.actions
|
|
610
|
+
[add_to_context(
|
|
611
|
+
:strongest_avenger => :thor,
|
|
612
|
+
:last_jedi => "Rey"
|
|
613
|
+
)]
|
|
614
|
+
end
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
class AnOrganizerThatAddsAliases
|
|
618
|
+
extend FunctionalLightService::Organizer
|
|
619
|
+
|
|
620
|
+
def self.call
|
|
621
|
+
with(:foo => :bar).reduce(actions)
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
def self.actions
|
|
625
|
+
[add_aliases(:foo => :baz)]
|
|
626
|
+
end
|
|
627
|
+
end
|
|
628
|
+
end
|