trailblazer-macro 2.1.11 → 2.1.13
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/ci.yml +6 -4
- data/.github/workflows/ci_jruby.yml +19 -0
- data/.github/workflows/ci_legacy.yml +19 -0
- data/.github/workflows/ci_truffleruby.yml +19 -0
- data/CHANGES.md +33 -0
- data/Gemfile +7 -5
- data/lib/trailblazer/macro/each.rb +187 -0
- data/lib/trailblazer/macro/model.rb +4 -5
- data/lib/trailblazer/macro/nested.rb +130 -68
- data/lib/trailblazer/macro/rescue.rb +2 -0
- data/lib/trailblazer/macro/strategy.rb +32 -0
- data/lib/trailblazer/macro/version.rb +1 -1
- data/lib/trailblazer/macro/wrap.rb +72 -65
- data/lib/trailblazer/macro.rb +53 -2
- data/test/docs/autogenerated/operation_each_test.rb +585 -0
- data/test/docs/autogenerated/operation_model_test.rb +263 -0
- data/test/docs/each_test.rb +940 -0
- data/test/docs/macro_test.rb +18 -0
- data/test/docs/model_test.rb +204 -88
- data/test/docs/nested_static_test.rb +730 -0
- data/test/docs/wrap_test.rb +348 -66
- data/test/test_helper.rb +29 -0
- data/trailblazer-macro.gemspec +2 -6
- metadata +21 -58
- data/.rubocop.yml +0 -6
- data/.rubocop_todo.yml +0 -423
- data/test/docs/nested_test.rb +0 -218
- data/test/operation/model_test.rb +0 -89
- data/test/operation/nested_test.rb +0 -98
@@ -0,0 +1,585 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
module Autogenerated
|
3
|
+
|
4
|
+
# step Macro::Each(:report_templates, key: :report_template) {
|
5
|
+
# step Subprocess(ReportTemplate::Update), input: :input_report_template
|
6
|
+
# fail :set_report_template_errors
|
7
|
+
# }
|
8
|
+
|
9
|
+
# def report_templates(ctx, **) ctx["result.contract.default"].report_templates
|
10
|
+
# end
|
11
|
+
|
12
|
+
class EachTest < Minitest::Spec
|
13
|
+
class Composer < Struct.new(:full_name, :email)
|
14
|
+
end
|
15
|
+
|
16
|
+
class Mailer
|
17
|
+
def self.send(**options)
|
18
|
+
@send_options << options
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
attr_accessor :send_options
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
#@ operation has {#composers_for_each}
|
27
|
+
module B
|
28
|
+
class Song < Struct.new(:id, :title, :band, :composers)
|
29
|
+
def self.find_by(id:)
|
30
|
+
if id == 2
|
31
|
+
return Song.new(id, nil, nil, [Composer.new("Fat Mike", "mike@fat.wreck"), Composer.new("El Hefe")])
|
32
|
+
end
|
33
|
+
|
34
|
+
if id == 3
|
35
|
+
return Song.new(id, nil, nil, [Composer.new("Fat Mike", "mike@fat.wreck"), Composer.new("El Hefe", "scammer@spam")])
|
36
|
+
end
|
37
|
+
|
38
|
+
Song.new(id, nil, nil, [Composer.new("Fat Mike"), Composer.new("El Hefe")])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
#:each
|
43
|
+
module Song::Operation
|
44
|
+
class Cover < Trailblazer::Operation
|
45
|
+
step :model
|
46
|
+
#:each-dataset
|
47
|
+
step Each(dataset_from: :composers_for_each, collect: true) {
|
48
|
+
step :notify_composers
|
49
|
+
}
|
50
|
+
#:each-dataset end
|
51
|
+
step :rearrange
|
52
|
+
|
53
|
+
# "decider interface"
|
54
|
+
def composers_for_each(ctx, model:, **)
|
55
|
+
model.composers
|
56
|
+
end
|
57
|
+
|
58
|
+
def notify_composers(ctx, index:, item:, **)
|
59
|
+
ctx[:value] = [index, item.full_name]
|
60
|
+
end
|
61
|
+
|
62
|
+
#~meths
|
63
|
+
def model(ctx, params:, **)
|
64
|
+
ctx[:model] = Song.find_by(id: params[:id])
|
65
|
+
end
|
66
|
+
|
67
|
+
include T.def_steps(:rearrange)
|
68
|
+
#~meths end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
#:each end
|
72
|
+
end # B
|
73
|
+
|
74
|
+
it "allows a dataset compute in the hosting activity" do
|
75
|
+
#@ {:dataset} is not part of the {ctx}.
|
76
|
+
assert_invoke B::Song::Operation::Cover, params: {id: 1},
|
77
|
+
expected_ctx_variables: {
|
78
|
+
model: B::Song.find_by(id: 1),
|
79
|
+
collected_from_each: [[0, "Fat Mike"], [1, "El Hefe"],]
|
80
|
+
},
|
81
|
+
seq: "[:rearrange]"
|
82
|
+
|
83
|
+
=begin
|
84
|
+
#:collected_from_each
|
85
|
+
#~ctx_to_result
|
86
|
+
ctx = {params: {id: 1}} # Song 1 has two composers.
|
87
|
+
|
88
|
+
result = Song::Operation::Cover.(ctx)
|
89
|
+
|
90
|
+
puts result[:collected_from_each] #=> [[0, "Fat Mike"], [1, "El Hefe"]]
|
91
|
+
#~ctx_to_result end
|
92
|
+
#:collected_from_each end
|
93
|
+
=end
|
94
|
+
end
|
95
|
+
|
96
|
+
module CoverMethods
|
97
|
+
def notify_composers(ctx, index:, item:, **)
|
98
|
+
ctx[:value] = [index, item.full_name]
|
99
|
+
end
|
100
|
+
|
101
|
+
def model(ctx, params:, **)
|
102
|
+
ctx[:model] = EachTest::B::Song.find_by(id: params[:id])
|
103
|
+
end
|
104
|
+
|
105
|
+
include T.def_steps(:rearrange)
|
106
|
+
end
|
107
|
+
|
108
|
+
module ComposersForEach
|
109
|
+
def composers_for_each(ctx, model:, **)
|
110
|
+
model.composers
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
#@ operation has dedicated step {#find_composers}
|
115
|
+
module C
|
116
|
+
class Song < B::Song; end
|
117
|
+
|
118
|
+
module Song::Operation
|
119
|
+
class Cover < Trailblazer::Operation
|
120
|
+
step :model
|
121
|
+
step :find_composers
|
122
|
+
step Each(collect: true) {
|
123
|
+
step :notify_composers
|
124
|
+
}, In() => {:composers => :dataset}
|
125
|
+
step :rearrange
|
126
|
+
|
127
|
+
def find_composers(ctx, model:, **)
|
128
|
+
# You could also say {ctx[:dataset] = model.composers},
|
129
|
+
# and wouldn't need the In() mapping.
|
130
|
+
ctx[:composers] = model.composers
|
131
|
+
end
|
132
|
+
#~meths
|
133
|
+
include CoverMethods
|
134
|
+
#~meths end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end # C
|
138
|
+
|
139
|
+
it "dataset can come from the hosting activity" do
|
140
|
+
#@ {:dataset} is not part of the outgoing {ctx}.
|
141
|
+
assert_invoke B::Song::Operation::Cover, params: {id: 1},
|
142
|
+
expected_ctx_variables: {
|
143
|
+
model: B::Song.find_by(id: 1),
|
144
|
+
collected_from_each: [[0, "Fat Mike"], [1, "El Hefe"],]
|
145
|
+
}, seq: "[:rearrange]"
|
146
|
+
end
|
147
|
+
|
148
|
+
it "dataset coming via In() from the operation" do
|
149
|
+
#@ {:dataset} is not part of the {ctx}.
|
150
|
+
assert_invoke C::Song::Operation::Cover, params: {id: 1},
|
151
|
+
expected_ctx_variables: {
|
152
|
+
model: C::Song.find_by(id: 1),
|
153
|
+
composers: [Composer.new("Fat Mike"), Composer.new("El Hefe")],
|
154
|
+
collected_from_each: [[0, "Fat Mike"], [1, "El Hefe"],]
|
155
|
+
}, seq: "[:rearrange]"
|
156
|
+
end
|
157
|
+
|
158
|
+
#@ {:item_key}
|
159
|
+
module E
|
160
|
+
class Song < B::Song; end
|
161
|
+
|
162
|
+
Mailer = Class.new(EachTest::Mailer)
|
163
|
+
|
164
|
+
#:composer
|
165
|
+
module Song::Operation
|
166
|
+
class Cover < Trailblazer::Operation
|
167
|
+
#~meths
|
168
|
+
step :model
|
169
|
+
#:item_key
|
170
|
+
step Each(dataset_from: :composers_for_each, item_key: :composer) {
|
171
|
+
step :notify_composers
|
172
|
+
}
|
173
|
+
#:item_key end
|
174
|
+
step :rearrange
|
175
|
+
|
176
|
+
|
177
|
+
# circuit-step interface! "decider interface"
|
178
|
+
def composers_for_each(ctx, model:, **)
|
179
|
+
model.composers
|
180
|
+
end
|
181
|
+
include CoverMethods
|
182
|
+
#~meths end
|
183
|
+
def notify_composers(ctx, index:, composer:, **)
|
184
|
+
Mailer.send(to: composer.email, message: "#{index}) You, #{composer.full_name}, have been warned about your song being copied.")
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
#:composer end
|
189
|
+
end # E
|
190
|
+
|
191
|
+
it "{item_key: :composer}" do
|
192
|
+
E::Mailer.send_options = []
|
193
|
+
assert_invoke E::Song::Operation::Cover, params: {id: 1},
|
194
|
+
expected_ctx_variables: {
|
195
|
+
model: B::Song.find_by(id: 1),
|
196
|
+
# collected_from_each: ["Fat Mike", "El Hefe"]
|
197
|
+
},
|
198
|
+
seq: "[:rearrange]"
|
199
|
+
assert_equal E::Mailer.send_options, [{:to=>nil, :message=>"0) You, Fat Mike, have been warned about your song being copied."}, {:to=>nil, :message=>"1) You, El Hefe, have been warned about your song being copied."}]
|
200
|
+
end
|
201
|
+
|
202
|
+
#@ failure in Each
|
203
|
+
module F
|
204
|
+
class Song < B::Song; end
|
205
|
+
|
206
|
+
class Notify
|
207
|
+
def self.send_email(email)
|
208
|
+
return if email.nil?
|
209
|
+
true
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
module Song::Operation
|
214
|
+
class Cover < Trailblazer::Operation
|
215
|
+
step :model
|
216
|
+
step Each(dataset_from: :composers_for_each, collect: true) {
|
217
|
+
step :notify_composers
|
218
|
+
}
|
219
|
+
step :rearrange
|
220
|
+
|
221
|
+
def notify_composers(ctx, item:, **)
|
222
|
+
if Notify.send_email(item.email)
|
223
|
+
ctx[:value] = item.email # let's collect all emails that could be sent.
|
224
|
+
return true
|
225
|
+
else
|
226
|
+
return false
|
227
|
+
end
|
228
|
+
end
|
229
|
+
#~meths
|
230
|
+
|
231
|
+
# circuit-step interface! "decider interface"
|
232
|
+
def composers_for_each(ctx, model:, **)
|
233
|
+
model.composers
|
234
|
+
end
|
235
|
+
include CoverMethods
|
236
|
+
#~meths end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end # F
|
240
|
+
|
241
|
+
it "failure in Each" do
|
242
|
+
assert_invoke F::Song::Operation::Cover, params: {id: 2},
|
243
|
+
expected_ctx_variables: {
|
244
|
+
model: B::Song.find_by(id: 2),
|
245
|
+
collected_from_each: ["mike@fat.wreck", nil],
|
246
|
+
},
|
247
|
+
seq: "[]",
|
248
|
+
terminus: :failure
|
249
|
+
|
250
|
+
Trailblazer::Developer.wtf?(F::Song::Operation::Cover, [{params: {id: 2}, seq: []}])
|
251
|
+
end
|
252
|
+
|
253
|
+
|
254
|
+
#@ Each with operation
|
255
|
+
module D
|
256
|
+
class Song < B::Song; end
|
257
|
+
Mailer = Class.new(EachTest::Mailer)
|
258
|
+
|
259
|
+
#:operation-class
|
260
|
+
module Song::Operation
|
261
|
+
class Notify < Trailblazer::Operation
|
262
|
+
step :send_email
|
263
|
+
|
264
|
+
def send_email(ctx, index:, item:, **)
|
265
|
+
Mailer.send(to: item.email, message: "#{index}) You, #{item.full_name}, have been warned about your song being copied.")
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
#:operation-class end
|
270
|
+
|
271
|
+
#:operation
|
272
|
+
module Song::Operation
|
273
|
+
class Cover < Trailblazer::Operation
|
274
|
+
step :model
|
275
|
+
step Each(Notify, dataset_from: :composers_for_each)
|
276
|
+
step :rearrange
|
277
|
+
#~meths
|
278
|
+
def composers_for_each(ctx, model:, **)
|
279
|
+
model.composers
|
280
|
+
end
|
281
|
+
include CoverMethods
|
282
|
+
#~meths end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
#:operation end
|
286
|
+
end
|
287
|
+
|
288
|
+
it "Each(Activity::Railway)" do
|
289
|
+
D::Mailer.send_options = []
|
290
|
+
assert_invoke D::Song::Operation::Cover, params: {id: 1},
|
291
|
+
seq: "[:rearrange]",
|
292
|
+
expected_ctx_variables: {
|
293
|
+
model: D::Song.find_by(id: 1),
|
294
|
+
# collected_from_each: [[0, "Fat Mike"], [1, "El Hefe"],]
|
295
|
+
}
|
296
|
+
assert_equal D::Mailer.send_options, [{:to=>nil, :message=>"0) You, Fat Mike, have been warned about your song being copied."}, {:to=>nil, :message=>"1) You, El Hefe, have been warned about your song being copied."}]
|
297
|
+
end
|
298
|
+
|
299
|
+
#@ Each with operation with three outcomes. Notify terminates on {End.spam_email},
|
300
|
+
# which is then routed to End.spam_alert in the hosting activity.
|
301
|
+
# NOTE: this is not documented, yet.
|
302
|
+
module G
|
303
|
+
class Song < B::Song; end
|
304
|
+
|
305
|
+
module Song::Operation
|
306
|
+
class Notify < Trailblazer::Operation
|
307
|
+
terminus :spam_email
|
308
|
+
# SpamEmail = Class.new(Trailblazer::Operation::Signal)
|
309
|
+
|
310
|
+
step :send_email, Output(:failure) => Track(:spam_email)
|
311
|
+
|
312
|
+
def send_email(ctx, index:, item:, **)
|
313
|
+
return false if item.email == "scammer@spam"
|
314
|
+
ctx[:value] = [index, item.full_name]
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
module Song::Operation
|
320
|
+
class Cover < Trailblazer::Operation
|
321
|
+
terminus :spam_alert
|
322
|
+
|
323
|
+
step :model
|
324
|
+
step Each(Notify, dataset_from: :composers_for_each, collect: true),
|
325
|
+
Output(:spam_email) => Track(:spam_alert)
|
326
|
+
step :rearrange
|
327
|
+
#~meths
|
328
|
+
def composers_for_each(ctx, model:, **)
|
329
|
+
model.composers
|
330
|
+
end
|
331
|
+
include CoverMethods
|
332
|
+
#~meths end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
it "Each(Activity::Railway) with End.spam_email" do
|
338
|
+
Trailblazer::Developer.wtf?(G::Song::Operation::Cover, [{params: {id: 3}}, {}])
|
339
|
+
|
340
|
+
assert_invoke G::Song::Operation::Cover, params: {id: 3},
|
341
|
+
terminus: :spam_alert,
|
342
|
+
seq: "[]",
|
343
|
+
expected_ctx_variables: {
|
344
|
+
model: G::Song.find_by(id: 3),
|
345
|
+
collected_from_each: [[0, "Fat Mike"], nil,]
|
346
|
+
}
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
#@ Iteration doesn't add anything to ctx when {collect: false}.
|
351
|
+
class EachCtxDiscardedTest < Minitest::Spec
|
352
|
+
Composer = EachTest::Composer
|
353
|
+
Song = Class.new(EachTest::B::Song)
|
354
|
+
|
355
|
+
#@ iterated steps write to ctx, gets discarded.
|
356
|
+
module Song::Operation
|
357
|
+
class Cover < Trailblazer::Operation
|
358
|
+
step :model
|
359
|
+
#:write_to_ctx
|
360
|
+
step Each(dataset_from: :composers_for_each) {
|
361
|
+
step :notify_composers
|
362
|
+
step :write_to_ctx
|
363
|
+
}
|
364
|
+
#:write_to_ctx end
|
365
|
+
step :rearrange
|
366
|
+
|
367
|
+
#:write
|
368
|
+
def write_to_ctx(ctx, index:, seq:, **)
|
369
|
+
#~meths
|
370
|
+
seq << :write_to_ctx
|
371
|
+
|
372
|
+
#~meths end
|
373
|
+
ctx[:variable] = index # this is discarded!
|
374
|
+
end
|
375
|
+
#:write end
|
376
|
+
|
377
|
+
#~meths
|
378
|
+
include EachTest::CoverMethods
|
379
|
+
include EachTest::ComposersForEach
|
380
|
+
#~meths end
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
it "discards {ctx[:variable]}" do
|
385
|
+
assert_invoke Song::Operation::Cover, params: {id: 1},
|
386
|
+
expected_ctx_variables: {
|
387
|
+
model: Song.find_by(id: 1),
|
388
|
+
# collected_from_each: [[0, "Fat Mike"], [1, "El Hefe"],]
|
389
|
+
},
|
390
|
+
seq: "[:write_to_ctx, :write_to_ctx, :rearrange]"
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
# We add {:collected_from_each} ourselves.
|
395
|
+
class EachCtxAddsCollectedFromEachTest < Minitest::Spec
|
396
|
+
Composer = EachTest::Composer
|
397
|
+
Song = Class.new(EachTest::B::Song)
|
398
|
+
|
399
|
+
module Song::Operation
|
400
|
+
class Cover < Trailblazer::Operation
|
401
|
+
step :model
|
402
|
+
step Each(dataset_from: :composers_for_each,
|
403
|
+
|
404
|
+
# all filters called before/after each iteration!
|
405
|
+
Inject(:collected_from_each) => ->(ctx, **) { [] }, # this is called only once.
|
406
|
+
Out() => ->(ctx, collected_from_each:, **) { {collected_from_each: collected_from_each += [ctx[:value]] } }
|
407
|
+
|
408
|
+
|
409
|
+
|
410
|
+
) {
|
411
|
+
step :notify_composers
|
412
|
+
step :write_to_ctx
|
413
|
+
}
|
414
|
+
step :rearrange
|
415
|
+
|
416
|
+
def write_to_ctx(ctx, index:, seq:, item:, **)
|
417
|
+
seq << :write_to_ctx
|
418
|
+
|
419
|
+
ctx[:value] = [index, item.full_name]
|
420
|
+
end
|
421
|
+
|
422
|
+
#~meths
|
423
|
+
include EachTest::CoverMethods
|
424
|
+
include EachTest::ComposersForEach
|
425
|
+
#~meths end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
it "provides {:collected_from_each}" do
|
430
|
+
assert_invoke Song::Operation::Cover, params: {id: 1},
|
431
|
+
expected_ctx_variables: {
|
432
|
+
model: Song.find_by(id: 1),
|
433
|
+
collected_from_each: [[0, "Fat Mike"], [1, "El Hefe"],]
|
434
|
+
},
|
435
|
+
seq: "[:write_to_ctx, :write_to_ctx, :rearrange]"
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
#@ You can use Inject() to compute new variables.
|
440
|
+
#@ and Out() to compute what goes into the iterated {ctx}.
|
441
|
+
class EachCtxInOutTest < Minitest::Spec
|
442
|
+
Composer = EachTest::Composer
|
443
|
+
Song = Class.new(EachTest::B::Song)
|
444
|
+
|
445
|
+
module Song::Operation
|
446
|
+
class Cover < Trailblazer::Operation
|
447
|
+
step :model
|
448
|
+
step Each(dataset_from: :composers_for_each,
|
449
|
+
# Inject(always: true) => {
|
450
|
+
Inject(:composer_index) => ->(ctx, index:, **) { index },
|
451
|
+
# all filters called before/after each iteration!
|
452
|
+
Out() => ->(ctx, index:, variable:, **) { {:"composer-#{index}-value" => variable} }
|
453
|
+
|
454
|
+
|
455
|
+
|
456
|
+
|
457
|
+
|
458
|
+
) {
|
459
|
+
step :notify_composers
|
460
|
+
step :write_to_ctx
|
461
|
+
}
|
462
|
+
step :rearrange
|
463
|
+
|
464
|
+
def write_to_ctx(ctx, composer_index:, model:, **)
|
465
|
+
ctx[:variable] = "#{composer_index} + #{model.class.name.split('::').last}"
|
466
|
+
end
|
467
|
+
|
468
|
+
#~meths
|
469
|
+
include EachTest::CoverMethods
|
470
|
+
include EachTest::ComposersForEach
|
471
|
+
#~meths end
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
it "discards {ctx[:variable]}" do
|
476
|
+
assert_invoke Song::Operation::Cover, params: {id: 1},
|
477
|
+
expected_ctx_variables: {
|
478
|
+
model: Song.find_by(id: 1),
|
479
|
+
:"composer-0-value" => "0 + Song",
|
480
|
+
:"composer-1-value" => "1 + Song",
|
481
|
+
},
|
482
|
+
seq: "[:rearrange]"
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
class EachOuterCtxTest < Minitest::Spec
|
487
|
+
|
488
|
+
end
|
489
|
+
|
490
|
+
|
491
|
+
#@ {:errors} is first initialized with a default injection,
|
492
|
+
#@ then passed across iterations.
|
493
|
+
# TODO: similar test above with {:collected_from_each}.
|
494
|
+
class EachSharedIterationVariableTest < Minitest::Spec
|
495
|
+
Song = Class.new(EachTest::B::Song)
|
496
|
+
|
497
|
+
#:inject
|
498
|
+
module Song::Operation
|
499
|
+
class Cover < Trailblazer::Operation
|
500
|
+
step :model
|
501
|
+
step Each(dataset_from: :composers_for_each,
|
502
|
+
Inject(:messages) => ->(*) { {} },
|
503
|
+
|
504
|
+
# all filters called before/after each iteration!
|
505
|
+
Out() => [:messages]
|
506
|
+
) {
|
507
|
+
step :write_to_ctx
|
508
|
+
}
|
509
|
+
step :rearrange
|
510
|
+
|
511
|
+
def write_to_ctx(ctx, item:, messages:, index:, **)
|
512
|
+
ctx[:messages] = messages.merge(index => item.full_name)
|
513
|
+
end
|
514
|
+
#~meths
|
515
|
+
include EachTest::CoverMethods
|
516
|
+
include EachTest::ComposersForEach
|
517
|
+
#~meths end
|
518
|
+
end
|
519
|
+
end
|
520
|
+
#:inject end
|
521
|
+
|
522
|
+
it "passes {ctx[:messages]} across iterations and makes it grow" do
|
523
|
+
assert_invoke Song::Operation::Cover, params: {id: 1},
|
524
|
+
expected_ctx_variables: {
|
525
|
+
model: Song.find_by(id: 1),
|
526
|
+
messages: {0=>"Fat Mike", 1=>"El Hefe"}},
|
527
|
+
seq: "[:rearrange]"
|
528
|
+
end
|
529
|
+
|
530
|
+
end
|
531
|
+
|
532
|
+
#@ Each without any option
|
533
|
+
class EachPureTest < Minitest::Spec
|
534
|
+
Song = Class.new(EachTest::B::Song)
|
535
|
+
|
536
|
+
Mailer = Class.new(EachTest::Mailer)
|
537
|
+
|
538
|
+
#:each-pure
|
539
|
+
module Song::Operation
|
540
|
+
class Cover < Trailblazer::Operation
|
541
|
+
step :model
|
542
|
+
#:each-pure-macro
|
543
|
+
step Each(dataset_from: :composers_for_each) {
|
544
|
+
step :notify_composers
|
545
|
+
}
|
546
|
+
#:each-pure-macro end
|
547
|
+
step :rearrange
|
548
|
+
|
549
|
+
# "decider interface"
|
550
|
+
#:dataset_from
|
551
|
+
def composers_for_each(ctx, model:, **)
|
552
|
+
model.composers
|
553
|
+
end
|
554
|
+
#:dataset_from end
|
555
|
+
|
556
|
+
#:iterated
|
557
|
+
def notify_composers(ctx, index:, item:, **)
|
558
|
+
Mailer.send(to: item.email, message: "#{index}) You, #{item.full_name}, have been warned about your song being copied.")
|
559
|
+
end
|
560
|
+
#:iterated end
|
561
|
+
#~meths
|
562
|
+
def model(ctx, params:, **)
|
563
|
+
ctx[:model] = Song.find_by(id: params[:id])
|
564
|
+
end
|
565
|
+
|
566
|
+
include T.def_steps(:rearrange)
|
567
|
+
#~meths end
|
568
|
+
end
|
569
|
+
end
|
570
|
+
#:each-pure end
|
571
|
+
|
572
|
+
it "allows a dataset compute in the hosting activity" do
|
573
|
+
Mailer.send_options = []
|
574
|
+
#@ {:dataset} is not part of the {ctx}.
|
575
|
+
assert_invoke Song::Operation::Cover, params: {id: 1},
|
576
|
+
expected_ctx_variables: {
|
577
|
+
model: Song.find_by(id: 1),
|
578
|
+
},
|
579
|
+
seq: "[:rearrange]"
|
580
|
+
|
581
|
+
assert_equal Mailer.send_options, [{:to=>nil, :message=>"0) You, Fat Mike, have been warned about your song being copied."}, {:to=>nil, :message=>"1) You, El Hefe, have been warned about your song being copied."}]
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
end
|