trailblazer-operation 0.0.13 → 0.1.1

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -3
  3. data/CHANGES.md +44 -0
  4. data/Gemfile +13 -2
  5. data/Rakefile +8 -6
  6. data/lib/trailblazer/operation.rb +86 -12
  7. data/lib/trailblazer/operation/deprecated_macro.rb +19 -0
  8. data/lib/trailblazer/operation/inject.rb +34 -0
  9. data/lib/trailblazer/operation/inspect.rb +80 -0
  10. data/lib/trailblazer/operation/public_call.rb +62 -0
  11. data/lib/trailblazer/operation/railway.rb +32 -0
  12. data/lib/trailblazer/operation/railway/fast_track.rb +13 -0
  13. data/lib/trailblazer/operation/railway/normalizer.rb +73 -0
  14. data/lib/trailblazer/operation/railway/task_builder.rb +44 -0
  15. data/lib/trailblazer/operation/result.rb +6 -4
  16. data/lib/trailblazer/operation/skill.rb +8 -24
  17. data/lib/trailblazer/operation/task_wrap.rb +68 -0
  18. data/lib/trailblazer/operation/trace.rb +49 -0
  19. data/lib/trailblazer/operation/variable_mapping.rb +91 -0
  20. data/lib/trailblazer/operation/version.rb +1 -1
  21. data/test/call_test.rb +27 -8
  22. data/test/class_dependencies_test.rb +16 -0
  23. data/test/docs/doormat_test.rb +189 -0
  24. data/test/docs/wiring_test.rb +421 -0
  25. data/test/dry_container_test.rb +4 -0
  26. data/test/fast_track_test.rb +197 -0
  27. data/test/gemfiles/Gemfile.ruby-2.0 +1 -2
  28. data/test/gemfiles/Gemfile.ruby-2.0.lock +40 -0
  29. data/test/inheritance_test.rb +1 -1
  30. data/test/inspect_test.rb +43 -0
  31. data/test/introspect_test.rb +50 -0
  32. data/test/macro_test.rb +61 -0
  33. data/test/operation_test.rb +94 -0
  34. data/test/result_test.rb +14 -8
  35. data/test/ruby-2.0.0/operation_test.rb +73 -0
  36. data/test/ruby-2.0.0/step_test.rb +136 -0
  37. data/test/skill_test.rb +66 -48
  38. data/test/step_test.rb +228 -0
  39. data/test/task_wrap_test.rb +91 -0
  40. data/test/test_helper.rb +37 -0
  41. data/test/trace_test.rb +62 -0
  42. data/test/variable_mapping_test.rb +66 -0
  43. data/test/wire_test.rb +113 -0
  44. data/test/wiring/defaults_test.rb +197 -0
  45. data/test/wiring/subprocess_test.rb +70 -0
  46. data/trailblazer-operation.gemspec +3 -5
  47. metadata +62 -36
  48. data/lib/trailblazer/operation/1.9.3/option.rb +0 -36
  49. data/lib/trailblazer/operation/generic.rb +0 -12
  50. data/lib/trailblazer/operation/option.rb +0 -54
  51. data/lib/trailblazer/operation/pipetree.rb +0 -142
  52. data/lib/trailblazer/skill.rb +0 -70
  53. data/test/2.0.0-pipetree_test.rb +0 -100
  54. data/test/2.1.0-pipetree_test.rb +0 -100
  55. data/test/operation_skill_test.rb +0 -89
  56. data/test/pipetree_test.rb +0 -185
@@ -0,0 +1,16 @@
1
+ require "test_helper"
2
+
3
+ class ClassDependenciesTest < Minitest::Spec
4
+
5
+ #- Operation[] and Operation[]=
6
+
7
+ class Index < Trailblazer::Operation
8
+ extend ClassDependencies
9
+
10
+ self["model.class"] = Module
11
+
12
+ step ->(options, **) { options["a"] = options["model.class"] }
13
+ end
14
+
15
+ it { Index.({}).inspect("a", "model.class").must_equal %{<Result:true [Module, Module] >} }
16
+ end
@@ -0,0 +1,189 @@
1
+ require "test_helper"
2
+
3
+ class TemplateWithGroupTest < Minitest::Spec
4
+ module Memo; end
5
+
6
+ #:template
7
+ class Memo::Operation < Trailblazer::Operation
8
+ step :log_call, group: :start
9
+ step :log_success, group: :end, before: "End.success"
10
+ fail :log_errors, group: :end, before: "End.failure"
11
+ #~tmethods
12
+
13
+ # our success "end":
14
+ def log_call(options, **)
15
+ options["row"] = [:a]
16
+ end
17
+
18
+ # our success "end":
19
+ def log_success(options, **)
20
+ options["row"] << :z
21
+ end
22
+
23
+ def log_errors(options, **)
24
+ options["row"] << :f
25
+ end
26
+ #~tmethods end
27
+ end
28
+ #:template end
29
+
30
+ #:template-user
31
+ class Memo::Create < Memo::Operation
32
+ step :create_model
33
+ step :validate
34
+ step :save
35
+ #~meths
36
+ def create_model(options, **)
37
+ options["row"] << :l
38
+ end
39
+
40
+ def validate(options, **)
41
+ options["row"] << :b
42
+ end
43
+
44
+ def save(options, **)
45
+ options["row"] << :c
46
+ end
47
+ #~meths end
48
+ end
49
+ #:template-user end
50
+
51
+ # it { pp F['__sequence__'].to_a }
52
+ it { Memo::Create.(params: {}, "b_return" => false,
53
+ ).inspect("row").must_equal %{<Result:true [[:a, :l, :b, :c, :z]] >} }
54
+ end
55
+
56
+ class DoormatWithGroupTest < Minitest::Spec
57
+ module Memo; end
58
+
59
+ #:doormat-group
60
+ class Memo::Create < Trailblazer::Operation
61
+ step :create_model
62
+ step :log_success, group: :end, before: "End.success"
63
+
64
+ step :validate
65
+ step :save
66
+
67
+ fail :log_errors, group: :end, before: "End.failure"
68
+ #~methods
69
+ def create_model(options, **)
70
+ options["row"] = [:a]
71
+ end
72
+
73
+ # our success "end":
74
+ def log_success(options, **)
75
+ options["row"] << :z
76
+ end
77
+
78
+ # 2
79
+ def validate(options, **)
80
+ options["row"] << :b
81
+ end
82
+
83
+ # 3
84
+ def save(options, **)
85
+ options["row"] << :c
86
+ end
87
+
88
+ def log_errors(options, **)
89
+ options["row"] << :f
90
+ end
91
+ #~methods end
92
+ end
93
+ #:doormat-group end
94
+
95
+ # it { pp F['__sequence__'].to_a }
96
+ it { Memo::Create.(params: {}, "b_return" => false,
97
+ ).inspect("row").must_equal %{<Result:true [[:a, :b, :c, :z]] >} }
98
+ end
99
+
100
+ class DoormatStepDocsTest < Minitest::Spec
101
+ module Memo; end
102
+
103
+ #:doormat-before
104
+ class Memo::Create < Trailblazer::Operation
105
+ step :create_model
106
+ step :log_success
107
+
108
+ step :validate, before: :log_success
109
+ step :save, before: :log_success
110
+
111
+ fail :log_errors
112
+ #~im
113
+ def create_model(options, **)
114
+ options["row"] = [:a]
115
+ end
116
+
117
+ # our success "end":
118
+ def log_success(options, **)
119
+ options["row"] << :z
120
+ end
121
+
122
+ # 2
123
+ def validate(options, **)
124
+ options["row"] << :b
125
+ end
126
+
127
+ # 3
128
+ def save(options, **)
129
+ options["row"] << :c
130
+ end
131
+
132
+ def log_errors(options, **)
133
+ options["row"] << :f
134
+ end
135
+ #~im end
136
+ end
137
+ #:doormat-before end
138
+
139
+ # it { pp F['__sequence__'].to_a }
140
+ it { Memo::Create.(params: {}, "b_return" => false,
141
+ ).inspect("row").must_equal %{<Result:true [[:a, :b, :c, :z]] >} }
142
+ end
143
+
144
+ class DoormatInheritanceTest < Minitest::Spec
145
+ #:doormatx-before-inheritance
146
+ class Base < Trailblazer::Operation
147
+ step :log_success!
148
+ fail :log_errors!
149
+ #~ignored
150
+ # our success "end":
151
+ def log_success!(options, **)
152
+ options["row"] << :z
153
+ end
154
+
155
+ def log_errors!(options, **)
156
+ options["row"] << :f
157
+ end
158
+ #~ignored end
159
+ end
160
+ #:doormatx-before-inheritance end
161
+
162
+ #:doormat-before-inheritance-sub
163
+ class Create < Base
164
+ step :first, before: :log_success!
165
+ step :second, before: :log_success!
166
+ step :third, before: :log_success!
167
+ #~ignoredd
168
+ def first(options, **)
169
+ options["row"] = [:a]
170
+ end
171
+
172
+ # 2
173
+ def second(options, **)
174
+ options["row"] << :b
175
+ end
176
+
177
+ # 3
178
+ def third(options, **)
179
+ options["row"] << :c
180
+ end
181
+ #~ignoredd end
182
+ end
183
+ #:doormat-before-inheritance-sub end
184
+
185
+ # it { pp F['__sequence__'].to_a }
186
+ it { Create.({}, "b_return" => false,
187
+ ).inspect("row").must_equal %{<Result:true [[:a, :b, :c, :z]] >} }
188
+ end
189
+
@@ -0,0 +1,421 @@
1
+ require "test_helper"
2
+
3
+ class WiringDocsTest < Minitest::Spec
4
+ class Memo
5
+ def initialize(options={})
6
+ @options
7
+ end
8
+
9
+ def inspect
10
+ %{#<Memo text=#{text.inspect}>}
11
+ end
12
+
13
+ attr_accessor :id, :text
14
+ end
15
+
16
+ # _"Everything's a memo."_
17
+
18
+ module Step
19
+ #:memo-op
20
+ class Memo::Create < Trailblazer::Operation
21
+ step :create_model
22
+ step :validate
23
+ fail :assign_errors
24
+ step :index
25
+ pass :uuid
26
+ step :save
27
+ fail :log_errors
28
+ #~memo-methods
29
+ def create_model(options, **)
30
+ end
31
+ def validate(options, **)
32
+ end
33
+ def assign_errors(options, **)
34
+ end
35
+ def index(options, **)
36
+ end
37
+ def uuid(options, **)
38
+ end
39
+ def save(options, **)
40
+ end
41
+ def log_errors(options, **)
42
+ end
43
+ #~memo-methods end
44
+ end
45
+ #:memo-op end
46
+
47
+ end
48
+
49
+ it do
50
+ result = Memo::Create.( text: "Punk is not dead." )
51
+ end
52
+
53
+
54
+ module PassFast
55
+ #:pf-op
56
+ class Memo::Create < Trailblazer::Operation
57
+ step :create_model
58
+ step :validate, pass_fast: true
59
+ fail :assign_errors
60
+ step :index
61
+ pass :uuid
62
+ step :save
63
+ fail :log_errors
64
+ #~pf-methods
65
+ def create_model(options, **)
66
+ end
67
+ def validate(options, **)
68
+ end
69
+ def assign_errors(options, **)
70
+ end
71
+ def index(options, **)
72
+ end
73
+ def uuid(options, **)
74
+ end
75
+ def save(options, **)
76
+ end
77
+ def log_errors(options, **)
78
+ end
79
+ #~pf-methods end
80
+ end
81
+ #:pf-op end
82
+
83
+ end
84
+
85
+ module FailFast
86
+ #:ff-op
87
+ class Memo::Create < Trailblazer::Operation
88
+ step :create_model
89
+ step :validate
90
+ fail :assign_errors, fail_fast: true
91
+ step :index
92
+ pass :uuid
93
+ step :save
94
+ fail :log_errors
95
+ #~ff-methods
96
+ def create_model(options, **)
97
+ end
98
+ def validate(options, **)
99
+ end
100
+ def assign_errors(options, **)
101
+ end
102
+ def index(options, **)
103
+ end
104
+ def uuid(options, **)
105
+ end
106
+ def save(options, **)
107
+ end
108
+ def log_errors(options, **)
109
+ end
110
+ #~ff-methods end
111
+ end
112
+ #:ff-op end
113
+
114
+ end
115
+
116
+ module FailFast
117
+ #:ff-step-op
118
+ class Memo::Create < Trailblazer::Operation
119
+ step :create_model
120
+ step :validate
121
+ fail :assign_errors, fail_fast: true
122
+ step :index, fail_fast: true
123
+ pass :uuid
124
+ step :save
125
+ fail :log_errors
126
+ #~ff-step-methods
127
+ def create_model(options, **)
128
+ end
129
+ def validate(options, **)
130
+ end
131
+ def assign_errors(options, **)
132
+ end
133
+ def index(options, **)
134
+ end
135
+ def uuid(options, **)
136
+ end
137
+ def save(options, **)
138
+ end
139
+ def log_errors(options, **)
140
+ end
141
+ #~ff-step-methods end
142
+ end
143
+ #:ff-step-op end
144
+ end
145
+
146
+ =begin
147
+ describe all options :pass_fast, :fast_track and emiting signals directly, like Left.
148
+ =end
149
+ module FastTrack
150
+ class Memo < WiringDocsTest::Memo; end
151
+
152
+ #:ft-step-op
153
+ class Memo::Create < Trailblazer::Operation
154
+ step :create_model, fast_track: true
155
+ step :validate
156
+ fail :assign_errors, fast_track: true
157
+ step :index
158
+ pass :uuid
159
+ step :save
160
+ fail :log_errors
161
+ #~ft-step-methods
162
+ #:ft-create
163
+ def create_model(options, create_empty_model:false, **)
164
+ options[:model] = Memo.new
165
+ create_empty_model ? Railway.pass_fast! : true
166
+ end
167
+ #:ft-create end
168
+ #:signal-validate
169
+ def validate(options, params: {}, **)
170
+ if params[:text].nil?
171
+ Trailblazer::Activity::Left #=> left track, failure
172
+ else
173
+ Trailblazer::Activity::Right #=> right track, success
174
+ end
175
+ end
176
+ #:signal-validate end
177
+ def assign_errors(options, model:, **)
178
+ options[:errors] = "Something went wrong!"
179
+
180
+ model.id.nil? ? Railway.fail_fast! : false
181
+ end
182
+ def index(options, model:, **)
183
+ true
184
+ end
185
+ def uuid(options, **)
186
+ true
187
+ end
188
+ def save(options, model:, **)
189
+ model.id = 1
190
+ end
191
+ def log_errors(options, **)
192
+ end
193
+ #~ft-step-methods end
194
+ end
195
+ #:ft-step-op end
196
+
197
+ class Memo::Create2 < Memo::Create
198
+ #:signalhelper-validate
199
+ def validate(options, params: {}, **)
200
+ if params[:text].nil?
201
+ Railway.fail! #=> left track, failure
202
+ else
203
+ Railway.pass! #=> right track, success
204
+ end
205
+ end
206
+ #:signalhelper-validate end
207
+ end
208
+ end
209
+
210
+ it "runs #create_model, only" do
211
+ Memo = FastTrack::Memo
212
+ #:ft-call
213
+ result = Memo::Create.( create_empty_model: true )
214
+ puts result.success? #=> true
215
+ puts result[:model].inspect #=> #<Memo text=nil>
216
+ #:ft-call end
217
+
218
+ result.success?.must_equal true
219
+ result[:model].id.must_be_nil
220
+ end
221
+
222
+ it "fast-tracks in #assign_errors" do
223
+ Memo = FastTrack::Memo
224
+ #:ft-call-err
225
+ result = Memo::Create.( {} )
226
+ puts result.success? #=> false
227
+ puts result[:model].inspect #=> #<Memo text=nil>
228
+ puts result[:errors].inspect #=> "Something went wrong!"
229
+ #:ft-call-err end
230
+
231
+ result.success?.must_equal false
232
+ result[:model].id.must_be_nil
233
+ result[:errors].must_equal "Something went wrong!"
234
+ end
235
+
236
+ it "goes till #save by emitting signals directly" do
237
+ Memo = FastTrack::Memo
238
+ result = Memo::Create.( params: { text: "Punk is not dead!" } )
239
+ result.success?.must_equal true
240
+ result[:model].id.must_equal 1
241
+ result[:errors].must_be_nil
242
+ end
243
+
244
+ it "goes till #save by using signal helper" do
245
+ Memo = FastTrack::Memo
246
+ result = Memo::Create2.( params: { text: "Punk is not dead!" } )
247
+ result.success?.must_equal true
248
+ result[:model].id.must_equal 1
249
+ result[:errors].must_be_nil
250
+ end
251
+ end
252
+
253
+ =begin
254
+ :before, :after, :replace, :delete, :group, :id
255
+ =end
256
+ class WiringsDocSeqOptionsTest < Minitest::Spec
257
+ module Id
258
+ class Memo < WiringDocsTest::Memo; end
259
+
260
+ #:id
261
+ class Memo::Create < Trailblazer::Operation
262
+ step :create_model, id: "create_memo"
263
+ step :validate, id: "validate_params"
264
+ step :save
265
+ #~id-methods
266
+ def create_model(options, **)
267
+ end
268
+ def validate(options, **)
269
+ end
270
+ def save(options, **)
271
+ end
272
+ #~id-methods end
273
+ end
274
+ #:id end
275
+
276
+ #:delete
277
+ class Memo::Create::Admin < Memo::Create
278
+ step nil, delete: "validate_params", id: ""
279
+ end
280
+ #:delete end
281
+
282
+ #:before
283
+ class Memo::Create::Authorized < Memo::Create
284
+ step :policy, before: "create_memo"
285
+ #~before-methods
286
+ def policy(options, **)
287
+ end
288
+ #~before-methods end
289
+ end
290
+ #:before end
291
+
292
+ #:after
293
+ class Memo::Create::Logging < Memo::Create
294
+ step :logger, after: "validate_params"
295
+ #~after-methods
296
+ def logger(options, **)
297
+ end
298
+ #~after-methods end
299
+ end
300
+ #:after end
301
+
302
+ #:replace
303
+ class Memo::Update < Memo::Create
304
+ step :find_model, replace: "create_memo", id: "update_memo"
305
+ #~replace-methods
306
+ def find_model(options, **)
307
+ end
308
+ #~replace-methods end
309
+ end
310
+ #:replace end
311
+ end
312
+
313
+ it ":id shows up in introspect" do
314
+ Memo = Id::Memo
315
+ #:id-inspect
316
+ Trailblazer::Operation.introspect( Memo::Create )
317
+ #=> [>create_model,>validate_params,>save]
318
+ #:id-inspect end
319
+
320
+ Trailblazer::Operation.introspect( Memo::Create ).must_equal %{[>create_memo,>validate_params,>save]}
321
+ end
322
+
323
+ it ":delete removes step" do
324
+ Memo = Id::Memo
325
+ #:delete-inspect
326
+ Trailblazer::Operation.introspect( Memo::Create::Admin )
327
+ #=> [>create_model,>save]
328
+ #:delete-inspect end
329
+
330
+ Trailblazer::Operation.introspect( Memo::Create::Admin ).must_equal %{[>create_memo,>save]}
331
+ end
332
+
333
+ it ":before inserts" do
334
+ Memo = Id::Memo
335
+ #:before-inspect
336
+ Trailblazer::Operation.introspect( Memo::Create::Authorized )
337
+ #=> [>create_model,>save]
338
+ #:before-inspect end
339
+
340
+ Trailblazer::Operation.introspect( Memo::Create::Authorized ).must_equal %{[>policy,>create_memo,>validate_params,>save]}
341
+ end
342
+
343
+ it ":after inserts" do
344
+ Memo = Id::Memo
345
+ #:after-inspect
346
+ Trailblazer::Operation.introspect( Memo::Create::Logging )
347
+ #=> [>create_memo,>validate_params,>logger,>save]
348
+ #:after-inspect end
349
+
350
+ Trailblazer::Operation.introspect( Memo::Create::Logging ).must_equal %{[>create_memo,>validate_params,>logger,>save]}
351
+ end
352
+
353
+ it ":replace inserts" do
354
+ Memo = Id::Memo
355
+ #:replace-inspect
356
+ Trailblazer::Operation.introspect( Memo::Update )
357
+ #=> [>update_memo,>validate_params,>save]
358
+ #:replace-inspect end
359
+
360
+ Trailblazer::Operation.introspect( Memo::Update ).must_equal %{[>update_memo,>validate_params,>save]}
361
+ end
362
+ end
363
+
364
+ # @see https://github.com/trailblazer/trailblazer/issues/190#issuecomment-326992255
365
+ class WiringsDocRecoverTest < Minitest::Spec
366
+ Memo = WiringDocsTest::Memo
367
+
368
+ #:fail-success
369
+ class Memo::Upload < Trailblazer::Operation
370
+ step :upload_to_s3
371
+ fail :upload_to_azure, Output(:success) => :success
372
+ fail :upload_to_b2, Output(:success) => :success
373
+ fail :log_problem
374
+ #~fail-success-methods
375
+ #:fail-success-s3
376
+ def upload_to_s3(options, s3:, **)
377
+ options[:s3] = s3 # the actual upload is dispatched here and result collected.
378
+ end
379
+ #:fail-success-s3 end
380
+
381
+ def upload_to_azure(options, azure:, **)
382
+ options[:azure] = azure
383
+ end
384
+
385
+ def upload_to_b2(options, b2:, **)
386
+ options[:b2] = b2
387
+ end
388
+
389
+ def log_problem(options, **)
390
+ options[:problem] = "All uploads failed."
391
+ end
392
+ #~fail-success-methods end
393
+ end
394
+ #:fail-success end
395
+
396
+ let(:my_image) { "beautiful landscape" }
397
+
398
+ it "works for S3" do
399
+ result = Memo::Upload.( image: my_image, s3: true )
400
+
401
+ [ result.success?, result[:s3], result[:azure], result[:b2], result[:problem] ].must_equal [ true, true, nil, nil, nil ]
402
+ end
403
+
404
+ it "works for Azure" do
405
+ result = Memo::Upload.( image: my_image, azure: true, s3: false )
406
+
407
+ [ result.success?, result[:s3], result[:azure], result[:b2], result[:problem] ].must_equal [ true, false, true, nil, nil ]
408
+ end
409
+
410
+ it "works for B2" do
411
+ result = Memo::Upload.( image: my_image, b2: true, azure: false, s3: false )
412
+
413
+ [ result.success?, result[:s3], result[:azure], result[:b2], result[:problem] ].must_equal [ true, false, false, true, nil ]
414
+ end
415
+
416
+ it "fails for all" do
417
+ result = Memo::Upload.( image: my_image, b2: false, azure: false, s3: false )
418
+
419
+ [ result.success?, result[:s3], result[:azure], result[:b2], result[:problem] ].must_equal [ false, false, false, false, "All uploads failed." ]
420
+ end
421
+ end