trailblazer-operation 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -0
  3. data/.rubocop_todo.yml +223 -0
  4. data/.travis.yml +6 -7
  5. data/CHANGES.md +2 -14
  6. data/Gemfile +4 -2
  7. data/README.md +13 -2
  8. data/Rakefile +2 -2
  9. data/lib/trailblazer/operation.rb +53 -67
  10. data/lib/trailblazer/operation/class_dependencies.rb +1 -1
  11. data/lib/trailblazer/operation/container.rb +14 -0
  12. data/lib/trailblazer/operation/deprecated_macro.rb +2 -2
  13. data/lib/trailblazer/operation/inspect.rb +17 -27
  14. data/lib/trailblazer/operation/public_call.rb +16 -18
  15. data/lib/trailblazer/operation/railway.rb +2 -3
  16. data/lib/trailblazer/operation/railway/macaroni.rb +2 -2
  17. data/lib/trailblazer/operation/result.rb +14 -1
  18. data/lib/trailblazer/operation/trace.rb +5 -8
  19. data/lib/trailblazer/operation/version.rb +4 -2
  20. data/test/benchmark/skill_resolver_benchmark.rb +8 -9
  21. data/test/call_test.rb +56 -30
  22. data/test/callable_test.rb +147 -147
  23. data/test/class_dependencies_test.rb +6 -7
  24. data/test/docs/doormat_test.rb +13 -12
  25. data/test/docs/macaroni_test.rb +7 -9
  26. data/test/docs/operation_test.rb +69 -4
  27. data/test/docs/wiring_test.rb +98 -53
  28. data/test/dry_container_test.rb +4 -3
  29. data/test/fast_track_test.rb +24 -44
  30. data/test/inheritance_test.rb +13 -12
  31. data/test/inspect_test.rb +6 -7
  32. data/test/introspect_test.rb +6 -6
  33. data/test/operation_test.rb +17 -25
  34. data/test/result_test.rb +4 -4
  35. data/test/ruby-2.0.0/operation_test.rb +9 -9
  36. data/test/ruby-2.0.0/step_test.rb +17 -16
  37. data/test/step_test.rb +47 -42
  38. data/test/test_helper.rb +6 -13
  39. data/test/trace_test.rb +26 -26
  40. data/test/wiring/defaults_test.rb +29 -33
  41. data/trailblazer-operation.gemspec +7 -6
  42. metadata +26 -18
  43. data/lib/trailblazer/operation/heritage.rb +0 -30
  44. data/lib/trailblazer/operation/inject.rb +0 -36
  45. data/lib/trailblazer/operation/railway/fast_track.rb +0 -13
  46. data/lib/trailblazer/operation/railway/normalizer.rb +0 -58
  47. data/lib/trailblazer/operation/railway/task_builder.rb +0 -37
  48. data/test/macro_test.rb +0 -60
  49. data/test/task_wrap_test.rb +0 -97
@@ -16,7 +16,7 @@ class Trailblazer::Operation
16
16
  # The use of this module is not encouraged and it is only here for backward-compatibility.
17
17
  # Instead, please pass dependencies via containers, locals, or macros into the respective steps.
18
18
  module ClassDependencies
19
- def call_with_circuit_interface( (ctx, flow_options), **circuit_options )
19
+ def call_with_circuit_interface((ctx, flow_options), **circuit_options)
20
20
  @skills.each { |name, value| ctx[name] ||= value } # this resembles the behavior in 2.0. we didn't say we liked it.
21
21
 
22
22
  super
@@ -0,0 +1,14 @@
1
+ module Trailblazer
2
+ module Operation::Container
3
+ def options_for_public_call(options={}, *containers)
4
+ # generate the skill hash that embraces runtime options plus potential containers, the so called Runtime options.
5
+ # This wrapping is supposed to happen once in the entire system.
6
+
7
+ hash_transformer = ->(containers) { containers[0].to_hash } # FIXME: don't transform any containers into kw args.
8
+
9
+ immutable_options = Trailblazer::Context::ContainerChain.new([options, *containers], to_hash: hash_transformer)
10
+
11
+ Trailblazer::Context(immutable_options)
12
+ end
13
+ end
14
+ end
@@ -5,7 +5,7 @@ module Trailblazer
5
5
  def self.call(proc, options)
6
6
  warn %{[Trailblazer] Macros with API (input, options) are deprecated. Please use the "Task API" signature (options, flow_options) or use a simpler Callable. (#{proc})}
7
7
 
8
- wrapped_proc = ->( (options, flow_options), **circuit_options ) do
8
+ wrapped_proc = ->((options, flow_options), **circuit_options) do
9
9
  result = proc.(circuit_options[:exec_context], options) # run the macro, with the deprecated signature.
10
10
 
11
11
  direction = Activity::TaskBuilder.binary_signal_for(result, Activity::Right, Activity::Left)
@@ -13,7 +13,7 @@ module Trailblazer
13
13
  return direction, [options, flow_options]
14
14
  end
15
15
 
16
- options.merge( task: wrapped_proc )
16
+ options.merge(task: wrapped_proc)
17
17
  end
18
18
  end
19
19
  end
@@ -14,31 +14,21 @@ module Trailblazer
14
14
  module Operation::Inspect
15
15
  module_function
16
16
 
17
- def call(operation, options={ style: :line })
18
- # TODO: better introspection API.
17
+ def call(operation, options = {style: :line})
18
+ graph = Activity::Introspect::Graph(operation)
19
19
 
20
- alterations = Activity::Magnetic::Builder::Finalizer.adds_to_alterations(operation.to_h[:adds])
21
- # DISCUSS: any other way to retrieve the Alterations?
20
+ rows = graph.collect do |node, i|
21
+ next if node[:data][:stop_event] # DISCUSS: show this?
22
22
 
23
- # pp alterations
24
- railway = alterations.instance_variable_get(:@groups).instance_variable_get(:@groups)[:main]
23
+ created_by = node[:data][:dsl_track] || :pass
25
24
 
26
- rows = railway.each_with_index.collect do |element, i|
27
- magnetic_to, task, plus_poles = element.configuration
25
+ [i, [created_by, node.id]]
26
+ end.compact
28
27
 
29
- created_by =
30
- if magnetic_to == [:failure]
31
- :fail
32
- elsif plus_poles.size > 1
33
- plus_poles[0].color == plus_poles[1].color ? :pass : :step
34
- else
35
- :pass # this is wrong for Nested, sometimes
36
- end
37
-
38
- [ i, [ created_by, element.id ] ]
39
- end
28
+ rows = rows[1..-1] # remove start
40
29
 
41
30
  return inspect_line(rows) if options[:style] == :line
31
+
42
32
  return inspect_rows(rows)
43
33
  end
44
34
 
@@ -46,7 +36,7 @@ module Trailblazer
46
36
  @inspect[step]
47
37
  end
48
38
 
49
- Operator = { :fail => "<<", :pass => ">>", :step => ">"}
39
+ Operator = {fail: "<<", pass: ">>", step: ">"}
50
40
 
51
41
  def inspect_line(names)
52
42
  string = names.collect { |i, (end_of_edge, name)| "#{Operator[end_of_edge]}#{name}" }.join(",")
@@ -61,13 +51,13 @@ module Trailblazer
61
51
  padding = 38
62
52
 
63
53
  proc = if operator == "<<"
64
- sprintf("%- #{padding}s", op)
65
- elsif [">", ">>", "&"].include?(operator.to_s)
66
- sprintf("% #{padding}s", op)
67
- else
68
- pad = " " * ((padding - op.length) / 2)
69
- "#{pad}#{op}#{pad}"
70
- end
54
+ sprintf("%- #{padding}s", op)
55
+ elsif [">", ">>", "&"].include?(operator.to_s)
56
+ sprintf("% #{padding}s", op)
57
+ else
58
+ pad = " " * ((padding - op.length) / 2)
59
+ "#{pad}#{op}#{pad}"
60
+ end
71
61
 
72
62
  proc = proc.gsub(" ", "=")
73
63
 
@@ -15,41 +15,39 @@ module Trailblazer
15
15
  # @return Operation::Railway::Result binary result object
16
16
  def call(*args)
17
17
  return call_with_circuit_interface(*args) if args.any? && args[0].is_a?(Array) # This is kind of a hack that could be well hidden if Ruby had method overloading. Goal is to simplify the call/__call__ thing as we're fading out Operation::call anyway.
18
+
18
19
  call_with_public_interface(*args)
19
20
  end
20
21
 
21
22
  def call_with_public_interface(*args)
22
- ctx = Operation::PublicCall.options_for_public_call(*args)
23
+ ctx = options_for_public_call(*args)
23
24
 
24
25
  # call the activity.
25
26
  # This will result in invoking {::call_with_circuit_interface}.
26
- last_signal, (options, flow_options) = Activity::TaskWrap.invoke(self, [ctx, {}], {})
27
+ # last_signal, (options, flow_options) = Activity::TaskWrap.invoke(self, [ctx, {}], {})
28
+ signal, (ctx, flow_options) = Activity::TaskWrap.invoke(
29
+ @activity,
30
+ [ctx, {}],
31
+ exec_context: new
32
+ )
27
33
 
28
34
  # Result is successful if the activity ended with an End event derived from Railway::End::Success.
29
- Operation::Railway::Result(last_signal, options, flow_options)
35
+ Operation::Railway::Result(signal, ctx, flow_options)
30
36
  end
31
37
 
32
38
  # This interface is used for all nested OPs (and the outer-most, too).
33
39
  def call_with_circuit_interface(args, circuit_options)
34
- @activity.(
35
- args,
36
- circuit_options.merge(
37
- exec_context: new
38
- )
39
- )
40
+ strategy_call(args, circuit_options) # FastTrack#call
41
+ end
42
+
43
+ def options_for_public_call(*args)
44
+ Operation::PublicCall.options_for_public_call(*args)
40
45
  end
41
46
 
42
47
  # Compile a Context object to be passed into the Activity::call.
43
48
  # @private
44
- def self.options_for_public_call(options={}, *containers)
45
- # generate the skill hash that embraces runtime options plus potential containers, the so called Runtime options.
46
- # This wrapping is supposed to happen once in the entire system.
47
-
48
- hash_transformer = ->(containers) { containers[0].to_hash } # FIXME: don't transform any containers into kw args.
49
-
50
- immutable_options = Trailblazer::Context::ContainerChain.new( [options, *containers], to_hash: hash_transformer ) # Runtime options, immutable.
51
-
52
- ctx = Trailblazer::Context(immutable_options)
49
+ def self.options_for_public_call(options={})
50
+ Trailblazer::Context(options)
53
51
  end
54
52
  end
55
53
  end
@@ -23,10 +23,9 @@ module Trailblazer
23
23
  end
24
24
 
25
25
  module End
26
- class Success < Activity::End; end
27
- class Failure < Activity::End; end
26
+ Success = Activity::Railway::End::Success
27
+ Failure = Activity::Railway::End::Failure
28
28
  end
29
-
30
29
  end # Railway
31
30
  end
32
31
  end
@@ -7,13 +7,13 @@ module Trailblazer
7
7
  # def my_step( params:, options:, ** )
8
8
  module Macaroni
9
9
  def self.call(user_proc)
10
- Activity::TaskBuilder::Task.new( Trailblazer::Option.build( Macaroni::Option, user_proc ), user_proc )
10
+ Activity::TaskBuilder::Task.new(Trailblazer::Option.build(Macaroni::Option, user_proc), user_proc)
11
11
  end
12
12
 
13
13
  class Option < Trailblazer::Option
14
14
  # The Option#call! method prepares the arguments.
15
15
  def self.call!(proc, options, *)
16
- proc.( **options.to_hash.merge( options: options ) )
16
+ proc.(**options.to_hash.merge(options: options))
17
17
  end
18
18
  end
19
19
  end
@@ -11,7 +11,15 @@ class Trailblazer::Operation
11
11
  end
12
12
 
13
13
  def failure?
14
- ! success?
14
+ !success?
15
+ end
16
+
17
+ def to_hash
18
+ data.to_hash
19
+ end
20
+
21
+ def keys
22
+ data.to_hash.keys
15
23
  end
16
24
 
17
25
  extend Forwardable
@@ -20,11 +28,16 @@ class Trailblazer::Operation
20
28
  # DISCUSS: the two methods below are more for testing.
21
29
  def inspect(*slices)
22
30
  return "<Result:#{success?} #{slice(*slices).inspect} >" if slices.any?
31
+
23
32
  "<Result:#{success?} #{@data.inspect} >"
24
33
  end
25
34
 
26
35
  def slice(*keys)
27
36
  keys.collect { |k| self[k] }
28
37
  end
38
+
39
+ private
40
+
41
+ attr_reader :data
29
42
  end
30
43
  end
@@ -3,16 +3,13 @@ module Trailblazer
3
3
  module Trace
4
4
  # @note The problem in this method is, we have redundancy with Operation::PublicCall
5
5
  def self.call(operation, *args)
6
- ctx = PublicCall.options_for_public_call(*args) # redundant with PublicCall::call.
6
+ ctx = PublicCall.options_for_public_call(*args) # redundant with PublicCall::call.
7
7
 
8
- # Prepare the tracing-specific arguments. This is only run once for the entire circuit!
9
- operation, *args = Trailblazer::Activity::Trace.arguments_for_call( operation, [ctx, {}], {} )
8
+ stack, signal, (ctx, _flow_options) = Activity::Trace.(operation, [ctx, {}])
10
9
 
11
- last_signal, (ctx, flow_options) = Activity::TaskWrap.invoke(operation, *args )
10
+ result = Railway::Result(signal, ctx) # redundant with PublicCall::call.
12
11
 
13
- result = Railway::Result(last_signal, ctx) # redundant with PublicCall::call.
14
-
15
- Result.new(result, flow_options[:stack].to_a)
12
+ Result.new(result, stack.to_a)
16
13
  end
17
14
 
18
15
  # `Operation::trace` is included for simple tracing of the flow.
@@ -20,7 +17,7 @@ module Trailblazer
20
17
  #
21
18
  # @public
22
19
  #
23
- # Operation.trace(params, "current_user" => current_user).wtf
20
+ # Operation.trace(params, current_user: current_user).wtf
24
21
  def trace(*args)
25
22
  Trace.(self, *args)
26
23
  end
@@ -1,5 +1,7 @@
1
1
  module Trailblazer
2
- class Operation
3
- VERSION = "0.4.1"
2
+ module Version
3
+ module Operation
4
+ VERSION = "0.5.0"
5
+ end
4
6
  end
5
7
  end
@@ -11,28 +11,27 @@ normal_container = {}
11
11
  normal_container["xbla_#{i}"] = i
12
12
  end
13
13
 
14
-
15
14
  Benchmark.ips do |x|
16
- x.report(:merge) {
15
+ x.report(:merge) do
17
16
  attrs = normal_container.merge(initialize_hash)
18
- 10.times do |i|
17
+ 10.times do |_i|
19
18
  attrs["bla_8"]
20
19
  end
21
- 10.times do |i|
20
+ 10.times do |_i|
22
21
  attrs["xbla_1"]
23
22
  end
24
- }
23
+ end
25
24
 
26
- x.report(:resolver) {
25
+ x.report(:resolver) do
27
26
  attrs = Trailblazer::Skill::Resolver.new(initialize_hash, normal_container)
28
27
 
29
- 10.times do |i|
28
+ 10.times do |_i|
30
29
  attrs["bla_8"]
31
30
  end
32
- 10.times do |i|
31
+ 10.times do |_i|
33
32
  attrs["xbla_1"]
34
33
  end
35
- }
34
+ end
36
35
  end
37
36
 
38
37
  # Warming up --------------------------------------
data/test/call_test.rb CHANGED
@@ -1,47 +1,73 @@
1
1
  require "test_helper"
2
2
 
3
3
  class CallTest < Minitest::Spec
4
- describe "::call" do
5
- class Create < Trailblazer::Operation
6
- step ->(*) { true }
7
- def inspect
8
- "#{@skills.inspect}"
9
- end
4
+ class Create < Trailblazer::Operation
5
+ step ->(*) { true }
6
+ def inspect
7
+ @skills.inspect.to_s
10
8
  end
9
+ end
11
10
 
12
- it { Create.().must_be_instance_of Trailblazer::Operation::Railway::Result }
11
+ it { Create.().must_be_instance_of Trailblazer::Operation::Railway::Result }
13
12
 
14
- # it { Create.({}).inspect.must_equal %{<Result:true <Skill {} {\"params\"=>{}} {\"pipetree\"=>[>operation.new]}> >} }
15
- # it { Create.(name: "Jacob").inspect.must_equal %{<Result:true <Skill {} {\"params\"=>{:name=>\"Jacob\"}} {\"pipetree\"=>[>operation.new]}> >} }
16
- # it { Create.({ name: "Jacob" }, { policy: Object }).inspect.must_equal %{<Result:true <Skill {} {:policy=>Object, \"params\"=>{:name=>\"Jacob\"}} {\"pipetree\"=>[>operation.new]}> >} }
13
+ # it { Create.({}).inspect.must_equal %{<Result:true <Skill {} {\"params\"=>{}} {\"pipetree\"=>[>operation.new]}> >} }
14
+ # it { Create.(name: "Jacob").inspect.must_equal %{<Result:true <Skill {} {\"params\"=>{:name=>\"Jacob\"}} {\"pipetree\"=>[>operation.new]}> >} }
15
+ # it { Create.({ name: "Jacob" }, { policy: Object }).inspect.must_equal %{<Result:true <Skill {} {:policy=>Object, \"params\"=>{:name=>\"Jacob\"}} {\"pipetree\"=>[>operation.new]}> >} }
17
16
 
18
- #---
19
- # success?
20
- class Update < Trailblazer::Operation
21
- step ->(options, **) { options[:result] }
22
- end
17
+ #---
18
+ # success?
19
+ class Update < Trailblazer::Operation
20
+ step ->(ctx, **) { ctx[:result] }
21
+ end
23
22
 
24
- # operation success
25
- it do
26
- result = Update.(result: true)
23
+ # operation success
24
+ it do
25
+ result = Update.(result: true)
27
26
 
28
- result.success?.must_equal true
27
+ result.success?.must_equal true
29
28
 
30
- result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Success
31
- result.event.must_equal Update.outputs[:success].signal
32
- end
29
+ result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Success
30
+ result.event.must_equal Update.to_h[:outputs][0].signal
31
+ end
32
+
33
+ # operation failure
34
+ it do
35
+ result = Update.(result: false)
33
36
 
34
- # operation failure
35
- it do
36
- result = Update.(result: false)
37
+ result.success?.must_equal false
38
+ result.failure?.must_equal true
39
+
40
+ result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Failure
41
+ result.event.must_equal Update.to_h[:outputs].find { |output| output.semantic == :failure }.signal
42
+ end
37
43
 
38
- result.success?.must_equal false
39
- result.failure?.must_equal true
44
+ it "invokes with the taskWrap" do
45
+ operation = Class.new(Trailblazer::Operation) do
46
+ include Trailblazer::Activity::Testing.def_steps(:a)
40
47
 
41
- result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Failure
42
- result.event.must_equal Update.outputs[:failure].signal
48
+ def self.add_1(wrap_ctx, original_args)
49
+ ctx, = original_args[0]
50
+ ctx[:seq] << 1
51
+ return wrap_ctx, original_args # yay to mutable state. not.
52
+ end
53
+
54
+ merge = [
55
+ [Trailblazer::Activity::TaskWrap::Pipeline.method(:insert_before), "task_wrap.call_task", ["user.add_1", method(:add_1)]]
56
+ ]
57
+
58
+ step :a, extensions: [Trailblazer::Activity::TaskWrap::Extension(merge: merge)]
43
59
  end
44
60
 
61
+ # normal operation invocation
62
+ result = operation.(seq: [])
63
+
64
+ result.inspect(:seq).must_equal %{<Result:true [[1, :a]] >}
65
+
66
+ # with tracing
67
+ result = operation.trace(seq: [])
68
+
69
+ result.inspect(:seq).must_equal %{<Result:true [[1, :a]] >}
70
+
71
+ result.wtf?
45
72
  end
46
73
  end
47
-
@@ -1,147 +1,147 @@
1
- require "test_helper"
2
-
3
- class CallableHelper < Minitest::Spec
4
- Operation = Trailblazer::Operation
5
- Activity = Trailblazer::Activity
6
-
7
- module Blog
8
- Read = ->((options, *args), *) { options["Read"] = 1; [ Activity::Right, [options, *args] ] }
9
- Next = ->((options, *args), *) { options["NextPage"] = []; [ options["return"], [options, *args] ] }
10
- Comment = ->((options, *args), *) { options["Comment"] = 2; [ Activity::Right, [options, *args] ] }
11
- end
12
-
13
- module User
14
- Relax = ->((options, *args), *) { options["Relax"]=true; [ Activity::Right, [options, *args] ] }
15
- end
16
-
17
- ### Callable( )
18
- ###
19
- describe "circuit with 1 level of nesting" do # TODO: test this kind of configuration in dsl_tests somewhere.
20
- let(:blog) do
21
- Module.new do
22
- extend Activity::Path()
23
-
24
- task task: Blog::Read
25
- task task: Blog::Next, Output(Activity::Right, :done) => "End.success", Output(Activity::Left, :success) => Track(:success)
26
- task task: Blog::Comment
27
- end
28
- end
29
-
30
- let(:user) do
31
- _blog = blog
32
-
33
- Module.new do
34
- extend Activity::Path()
35
-
36
- task task: _blog, _blog.outputs[:success] => Track(:success)
37
- task task: User::Relax
38
- end
39
- end
40
-
41
- it "ends before comment, on next_page" do
42
- user.( [options = { "return" => Activity::Right }] ).must_equal(
43
- [user.outputs[:success].signal, [{"return"=>Trailblazer::Activity::Right, "Read"=>1, "NextPage"=>[], "Relax"=>true}]]
44
- )
45
-
46
- options.must_equal({"return"=>Trailblazer::Activity::Right, "Read"=>1, "NextPage"=>[], "Relax"=>true})
47
- end
48
- end
49
-
50
- ### Callable( End1, End2 )
51
- ###
52
- describe "circuit with 2 end events in the nested process" do
53
- let(:blog) do
54
- Module.new do
55
- extend Activity::Path()
56
-
57
- task task: Blog::Read
58
- task task: Blog::Next, Output(Activity::Right, :success___) => :__success, Output(Activity::Left, :retry___) => _retry=End(:retry)
59
- end
60
- end
61
-
62
- let(:user) do
63
- _blog = blog
64
-
65
- Module.new do
66
- extend Activity::Path()
67
-
68
- task task: _blog, _blog.outputs[:success] => Track(:success), _blog.outputs[:retry] => "End.success"
69
- task task: User::Relax
70
- end
71
- end
72
-
73
- it "runs from Callable->default to Relax" do
74
- user.( [ options = { "return" => Activity::Right } ] ).must_equal [
75
- user.outputs[:success].signal,
76
- [ {"return"=>Activity::Right, "Read"=>1, "NextPage"=>[], "Relax"=>true} ]
77
- ]
78
-
79
- options.must_equal({"return"=>Activity::Right, "Read"=>1, "NextPage"=>[], "Relax"=>true})
80
- end
81
-
82
- it "runs from other Callable end" do
83
- user.( [ options = { "return" => Activity::Left } ] ).must_equal [
84
- user.outputs[:success].signal,
85
- [ {"return"=>Activity::Left, "Read"=>1, "NextPage"=>[]} ]
86
- ]
87
-
88
- options.must_equal({"return"=>Activity::Left, "Read"=>1, "NextPage"=>[]})
89
- end
90
-
91
- #---
92
- #- Callable( activity, start_at )
93
- let(:with_nested_and_start_at) do
94
- _blog = blog
95
-
96
- Module.new do
97
- extend Activity::Path()
98
-
99
- task task: Operation::Callable( _blog, start_task: Blog::Next ), _blog.outputs[:success] => Track(:success)
100
- task task: User::Relax
101
- end
102
- end
103
-
104
- it "runs Callable from alternative start" do
105
- with_nested_and_start_at.( [options = { "return" => Activity::Right }] ).
106
- must_equal [
107
- with_nested_and_start_at.outputs[:success].signal,
108
- [ {"return"=>Activity::Right, "NextPage"=>[], "Relax"=>true} ]
109
- ]
110
-
111
- options.must_equal({"return"=>Activity::Right, "NextPage"=>[], "Relax"=>true})
112
- end
113
-
114
- #---
115
- #- Callable( activity, call: :__call__ ) { ... }
116
- describe "Callable with :call option" do
117
- let(:process) do
118
- class Workout
119
- def self.__call__((options, *args), *)
120
- options[:workout] = 9
121
-
122
- return Activity::Right, [options, *args]
123
- end
124
- end
125
-
126
- subprocess = Operation::Callable( Workout, call: :__call__ )
127
-
128
- Module.new do
129
- extend Activity::Path()
130
-
131
- task task: subprocess
132
- task task: User::Relax
133
- end
134
- end
135
-
136
- it "runs Callable process with __call__" do
137
- process.( [options = { "return" => Activity::Right }] ).
138
- must_equal [
139
- process.outputs[:success].signal,
140
- [{"return"=>Activity::Right, :workout=>9, "Relax"=>true}]
141
- ]
142
-
143
- options.must_equal({"return"=>Activity::Right, :workout=>9, "Relax"=>true})
144
- end
145
- end
146
- end
147
- end
1
+ # require "test_helper"
2
+
3
+ # class CallableHelper < Minitest::Spec
4
+ # Operation = Trailblazer::Operation
5
+ # Activity = Trailblazer::Activity
6
+
7
+ # module Blog
8
+ # Read = ->((options, *args), *) { options["Read"] = 1; [ Activity::Right, [options, *args] ] }
9
+ # Next = ->((options, *args), *) { options["NextPage"] = []; [ options["return"], [options, *args] ] }
10
+ # Comment = ->((options, *args), *) { options["Comment"] = 2; [ Activity::Right, [options, *args] ] }
11
+ # end
12
+
13
+ # module User
14
+ # Relax = ->((options, *args), *) { options["Relax"]=true; [ Activity::Right, [options, *args] ] }
15
+ # end
16
+
17
+ # ### Callable( )
18
+ # ###
19
+ # describe "circuit with 1 level of nesting" do # TODO: test this kind of configuration in dsl_tests somewhere.
20
+ # let(:blog) do
21
+ # Module.new do
22
+ # extend Activity::Path()
23
+
24
+ # task task: Blog::Read
25
+ # task task: Blog::Next, Output(Activity::Right, :done) => "End.success", Output(Activity::Left, :success) => Track(:success)
26
+ # task task: Blog::Comment
27
+ # end
28
+ # end
29
+
30
+ # let(:user) do
31
+ # _blog = blog
32
+
33
+ # Module.new do
34
+ # extend Activity::Path()
35
+
36
+ # task task: _blog, _blog.outputs[:success] => Track(:success)
37
+ # task task: User::Relax
38
+ # end
39
+ # end
40
+
41
+ # it "ends before comment, on next_page" do
42
+ # user.( [options = { "return" => Activity::Right }] ).must_equal(
43
+ # [user.outputs[:success].signal, [{"return"=>Trailblazer::Activity::Right, "Read"=>1, "NextPage"=>[], "Relax"=>true}]]
44
+ # )
45
+
46
+ # options.must_equal({"return"=>Trailblazer::Activity::Right, "Read"=>1, "NextPage"=>[], "Relax"=>true})
47
+ # end
48
+ # end
49
+
50
+ # ### Callable( End1, End2 )
51
+ # ###
52
+ # describe "circuit with 2 end events in the nested process" do
53
+ # let(:blog) do
54
+ # Module.new do
55
+ # extend Activity::Path()
56
+
57
+ # task task: Blog::Read
58
+ # task task: Blog::Next, Output(Activity::Right, :success___) => :__success, Output(Activity::Left, :retry___) => _retry=End(:retry)
59
+ # end
60
+ # end
61
+
62
+ # let(:user) do
63
+ # _blog = blog
64
+
65
+ # Module.new do
66
+ # extend Activity::Path()
67
+
68
+ # task task: _blog, _blog.outputs[:success] => Track(:success), _blog.outputs[:retry] => "End.success"
69
+ # task task: User::Relax
70
+ # end
71
+ # end
72
+
73
+ # it "runs from Callable->default to Relax" do
74
+ # user.( [ options = { "return" => Activity::Right } ] ).must_equal [
75
+ # user.outputs[:success].signal,
76
+ # [ {"return"=>Activity::Right, "Read"=>1, "NextPage"=>[], "Relax"=>true} ]
77
+ # ]
78
+
79
+ # options.must_equal({"return"=>Activity::Right, "Read"=>1, "NextPage"=>[], "Relax"=>true})
80
+ # end
81
+
82
+ # it "runs from other Callable end" do
83
+ # user.( [ options = { "return" => Activity::Left } ] ).must_equal [
84
+ # user.outputs[:success].signal,
85
+ # [ {"return"=>Activity::Left, "Read"=>1, "NextPage"=>[]} ]
86
+ # ]
87
+
88
+ # options.must_equal({"return"=>Activity::Left, "Read"=>1, "NextPage"=>[]})
89
+ # end
90
+
91
+ # #---
92
+ # #- Callable( activity, start_at )
93
+ # let(:with_nested_and_start_at) do
94
+ # _blog = blog
95
+
96
+ # Module.new do
97
+ # extend Activity::Path()
98
+
99
+ # task task: Operation::Callable( _blog, start_task: Blog::Next ), _blog.outputs[:success] => Track(:success)
100
+ # task task: User::Relax
101
+ # end
102
+ # end
103
+
104
+ # it "runs Callable from alternative start" do
105
+ # with_nested_and_start_at.( [options = { "return" => Activity::Right }] ).
106
+ # must_equal [
107
+ # with_nested_and_start_at.outputs[:success].signal,
108
+ # [ {"return"=>Activity::Right, "NextPage"=>[], "Relax"=>true} ]
109
+ # ]
110
+
111
+ # options.must_equal({"return"=>Activity::Right, "NextPage"=>[], "Relax"=>true})
112
+ # end
113
+
114
+ # #---
115
+ # #- Callable( activity, call: :__call__ ) { ... }
116
+ # describe "Callable with :call option" do
117
+ # let(:process) do
118
+ # class Workout
119
+ # def self.__call__((options, *args), *)
120
+ # options[:workout] = 9
121
+
122
+ # return Activity::Right, [options, *args]
123
+ # end
124
+ # end
125
+
126
+ # subprocess = Operation::Callable( Workout, call: :__call__ )
127
+
128
+ # Module.new do
129
+ # extend Activity::Path()
130
+
131
+ # task task: subprocess
132
+ # task task: User::Relax
133
+ # end
134
+ # end
135
+
136
+ # it "runs Callable process with __call__" do
137
+ # process.( [options = { "return" => Activity::Right }] ).
138
+ # must_equal [
139
+ # process.outputs[:success].signal,
140
+ # [{"return"=>Activity::Right, :workout=>9, "Relax"=>true}]
141
+ # ]
142
+
143
+ # options.must_equal({"return"=>Activity::Right, :workout=>9, "Relax"=>true})
144
+ # end
145
+ # end
146
+ # end
147
+ # end