trailblazer-activity 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bed08027bb74c9466a7dee0325bf2eb5fddc637eb2e46f3f86a3292e522fe083
4
- data.tar.gz: 3a89ef72fbbb55f084779cb376f68ef542486d4a5b0fe8af1200e594fea6f6b4
3
+ metadata.gz: b12275a2f1dfc9e9c90d7b3df76d2eab01db0964c453d61a23a307296cda2378
4
+ data.tar.gz: 93b881493ecec9eb50516cb1185ff1129c6fbc5efe478bc429604adae077c552
5
5
  SHA512:
6
- metadata.gz: 1c221eba23024d176d6c6c3376fd3aa6c5a668806d3b2cccd09e7a85496a07c833dddb74fa30e6c346eb0e8093b8186f1f8cc1557a21a37f1feddb7a9fabd7a9
7
- data.tar.gz: 27e679eab5c94988e821e05a7bdb25c301e656091f8bc100bb84a142cec3ec0f7fced3c61bb7ef0d5b2e89cd0847d22e7db2ca17c783906316628216dad93e12
6
+ metadata.gz: 7245451409ba95340e9a3ef5e9404df93b3e2f7aa9325fe2132bc45f4f7fbcd49370200dfe9532fb5fa8f4307fdd3f4c6eae480920927e232228361712ac8cef
7
+ data.tar.gz: a127529dea689958ff467558c6a373b37cfe0e2e2475b99b24f854488b672ff012cb8cccdfc3b02339e1b20e62eecbd92e5148fbe7e80ad5da7b8242e7f2c793
data/.travis.yml CHANGED
@@ -9,6 +9,6 @@ rvm:
9
9
  - 2.5.0
10
10
  matrix:
11
11
  include:
12
- - rvm: jruby-9.1.15.0
12
+ - rvm: jruby-head
13
13
  env: JRUBY_OPTS="--profile.api"
14
14
  before_install: gem install bundler
data/CHANGES.md CHANGED
@@ -1,3 +1,10 @@
1
+ # 0.4.3
2
+
3
+ * Make `:outputs` the canonical way to define outputs, and not `:plus_poles`. The latter is computed by the DSL if not passed.
4
+ * Allow injecting `inspect` implementations into `Introspect` methods.
5
+ * Add `Nested`.
6
+ * Add `TaskBuilder::Task#to_s`.
7
+
1
8
  # 0.4.2
2
9
 
3
10
  * `End` is not a `Struct` so we can maintain more state, and are immutable.
data/README.md CHANGED
@@ -4,7 +4,7 @@ The `activity` gem brings a light-weight DSL to define business processes, and t
4
4
 
5
5
  A process is a set of arbitrary pieces of logic you define, chained together and put into a meaningful context by an activity. Activity lets you focus on the implementation of steps while Trailblazer takes care of the control flow.
6
6
 
7
- Please find the [full documentation on the Trailblazer website](http://trailblazer.to/2.1/activity). [Note that the docs are WIP.]
7
+ Please find the [full documentation on the Trailblazer website](http://trailblazer.to/api-docs). [Note that the docs are WIP.]
8
8
 
9
9
  ## Example
10
10
 
@@ -0,0 +1,19 @@
1
+
2
+ module Inspect
3
+ def inspect
4
+ "nice view!"
5
+ end
6
+ end
7
+
8
+ module A
9
+ extend Inspect
10
+
11
+ def self.a
12
+ end
13
+ end
14
+
15
+ # jruby 9.1.7
16
+ puts A.method(:a).inspect #=> #<Method: A.a>
17
+ # 2.5
18
+ puts A.method(:a).inspect #=> #<Method: nice view!.a>
19
+
@@ -42,7 +42,7 @@ module Trailblazer
42
42
  module DSLHelper
43
43
  extend Forwardable
44
44
  def_delegators :@builder, :Path
45
- def_delegators DSL::Helper, :Output, :End
45
+ def_delegators DSL::Helper, :Output, :End, :Nested
46
46
 
47
47
  def Path(*args, &block)
48
48
  self[:builder].Path(*args, &block)
@@ -95,6 +95,7 @@ require "trailblazer/activity/config"
95
95
  require "trailblazer/activity/implementation/build_state"
96
96
  require "trailblazer/activity/implementation/interface"
97
97
  require "trailblazer/activity/implementation/path"
98
+ require "trailblazer/activity/implementation/plan"
98
99
  require "trailblazer/activity/implementation/railway"
99
100
  require "trailblazer/activity/implementation/fast_track"
100
101
 
@@ -44,6 +44,14 @@ module Trailblazer
44
44
  [ track_color, path ]
45
45
  }
46
46
  end
47
+
48
+ # Computes the :outputs options for {activity}
49
+ def Nested(activity)
50
+ {
51
+ task: activity,
52
+ outputs: activity.outputs
53
+ }
54
+ end
47
55
  end
48
56
  end
49
57
  end
@@ -22,6 +22,7 @@ class Trailblazer::Activity < Module
22
22
  return normalizer, options
23
23
  end
24
24
 
25
+ # @api private
25
26
  def self.build_state(normalizer, builder_class:, builder_options: {}, **options)
26
27
  builder, adds, circuit, outputs = State.build(builder_class, normalizer, options.merge(builder_options))
27
28
 
@@ -11,45 +11,13 @@ module Trailblazer
11
11
  {
12
12
  builder_class: Magnetic::Builder::Path, # we use the Activity-based Normalizer
13
13
  normalizer_class: Magnetic::Normalizer,
14
- plus_poles: Magnetic::Builder::Path.default_plus_poles,
14
+ default_outputs: Magnetic::Builder::Path.default_outputs,
15
15
  extension: [ Introspect.method(:add_introspection) ],
16
16
 
17
17
  extend: [ DSL.def_dsl(:task) ],
18
18
  }
19
19
  end
20
-
21
- def self.Plan()
22
- Plan
23
- end
24
-
25
- module Plan
26
- def self.extended(extended)
27
- extended.singleton_class.send :attr_accessor, :record
28
- extended.record = []
29
- extended.extend(Methods)
30
- end
31
-
32
- module Methods
33
- def task(*args, &block)
34
- record << [:task, args, block]
35
- end
36
- end
37
-
38
- def self.merge!(activity, plan)
39
- plan.record.each { |(dsl_method, args, block)| activity.send(dsl_method, *args, &block) }
40
- activity
41
- end
42
-
43
- # Creates a copy of the {activity} module and merges the {Plan} into it.
44
- #
45
- # @params activity [Activity] The activity to extend
46
- # @params plan [Plan] The plan providing additional steps
47
- # @return [Activity] A new, merged activity
48
- def self.merge(activity, plan)
49
- merge!(activity.clone, plan)
50
- end
51
- end
52
- end
20
+ end # Path
53
21
  end
54
22
  end
55
23
 
@@ -0,0 +1,36 @@
1
+ module Trailblazer
2
+ class Activity::Path < Activity
3
+ def self.Plan()
4
+ Plan
5
+ end
6
+
7
+ module Plan
8
+ def self.extended(extended)
9
+ extended.singleton_class.send :attr_accessor, :record
10
+ extended.record = []
11
+ extended.extend(Methods)
12
+ end
13
+
14
+ module Methods
15
+ def task(*args, &block)
16
+ record << [:task, args, block]
17
+ end
18
+ end
19
+
20
+ def self.merge!(activity, plan)
21
+ plan.record.each { |(dsl_method, args, block)| activity.send(dsl_method, *args, &block) }
22
+ activity
23
+ end
24
+
25
+ # Creates a copy of the {activity} module and merges the {Plan} into it.
26
+ #
27
+ # @params activity [Activity] The activity to extend
28
+ # @params plan [Plan] The plan providing additional steps
29
+ # @return [Activity] A new, merged activity
30
+ def self.merge(activity, plan)
31
+ merge!(activity.clone, plan)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -8,9 +8,9 @@ module Trailblazer
8
8
  class Railway < Activity
9
9
  def self.config
10
10
  Path.config.merge(
11
- builder_class: Magnetic::Builder::Railway,
12
- plus_poles: Magnetic::Builder::Railway.default_plus_poles,
13
- extend: [ DSL.def_dsl(:step), DSL.def_dsl(:fail), DSL.def_dsl(:pass) ],
11
+ builder_class: Magnetic::Builder::Railway,
12
+ default_outputs: Magnetic::Builder::Railway.default_outputs,
13
+ extend: [ DSL.def_dsl(:step), DSL.def_dsl(:fail), DSL.def_dsl(:pass) ],
14
14
  )
15
15
  end
16
16
  end
@@ -35,6 +35,11 @@ module Trailblazer
35
35
  end
36
36
 
37
37
 
38
+ def self.inspect_task_builder(task)
39
+ proc = task.instance_variable_get(:@user_proc)
40
+ %{#<TaskBuilder{#{proc}}>}
41
+ end
42
+
38
43
  # FIXME: clean up that shit below.
39
44
 
40
45
  # render
@@ -42,14 +47,14 @@ module Trailblazer
42
47
  circuit_hash( circuit.to_h[:map], **options )
43
48
  end
44
49
 
45
- def self.circuit_hash(circuit_hash, show_ids:false)
50
+ def self.circuit_hash(circuit_hash, show_ids:false, **options)
46
51
  content =
47
52
  circuit_hash.collect do |task, connections|
48
53
  conns = connections.collect do |signal, target|
49
- " {#{signal}} => #{Task(target)}"
54
+ " {#{signal}} => #{inspect_with_matcher(target, **options)}"
50
55
  end
51
56
 
52
- [ Task(task), conns.join("\n") ]
57
+ [ inspect_with_matcher(task, **options), conns.join("\n") ]
53
58
  end
54
59
 
55
60
  content = content.join("\n")
@@ -60,7 +65,7 @@ module Trailblazer
60
65
 
61
66
  def self.Ends(activity)
62
67
  end_events = activity.to_h[:end_events]
63
- ends = end_events.collect { |evt| Task(evt) }.join(",")
68
+ ends = end_events.collect { |evt| inspect_end(evt) }.join(",")
64
69
  "[#{ends}]".gsub(/\d\d+/, "")
65
70
  end
66
71
 
@@ -70,9 +75,17 @@ module Trailblazer
70
75
  join("\n").gsub(/0x\w+/, "").gsub(/\d\d+/, "")
71
76
  end
72
77
 
73
- def self.Task(task)
74
- return task.inspect unless task.kind_of?(Trailblazer::Activity::End)
78
+ # If Ruby had pattern matching, this function wasn't necessary.
79
+ def self.inspect_with_matcher(task, inspect_task: method(:inspect_task), inspect_end: method(:inspect_end))
80
+ return inspect_task.(task) unless task.kind_of?(Trailblazer::Activity::End)
81
+ inspect_end.(task)
82
+ end
83
+
84
+ def self.inspect_task(task)
85
+ task.inspect
86
+ end
75
87
 
88
+ def self.inspect_end(task)
76
89
  class_name = strip(task.class)
77
90
  options = task.to_h
78
91
 
@@ -108,7 +121,7 @@ module Trailblazer
108
121
  sequence.collect do |(magnetic_to, task, plus_poles)|
109
122
  pluses = plus_poles.collect { |plus_pole| PlusPole(plus_pole) }
110
123
 
111
- %{#{magnetic_to.inspect} ==> #{Activity::Introspect.Task(task)}
124
+ %{#{magnetic_to.inspect} ==> #{Activity::Introspect.inspect_with_matcher(task)}
112
125
  #{pluses.empty? ? " []" : pluses.join("\n")}}
113
126
  end.join("\n")
114
127
 
@@ -16,8 +16,8 @@ module Trailblazer
16
16
  end
17
17
 
18
18
  require "trailblazer/activity/magnetic/dsl"
19
- require "trailblazer/activity/magnetic/dsl/plus_poles"
20
- require "trailblazer/activity/magnetic/dsl/alterations"
19
+ require "trailblazer/activity/magnetic/structure/plus_poles"
20
+ require "trailblazer/activity/magnetic/structure/alterations"
21
21
 
22
22
  require "trailblazer/activity/schema/dependencies"
23
23
 
@@ -15,6 +15,7 @@ module Trailblazer
15
15
  end
16
16
  end
17
17
 
18
+ # Called from Path/Railway/FastTrack, creates the specific {Builder} instance.
18
19
  def self.Builder(implementation, normalizer, builder_options={})
19
20
  builder = implementation.new(normalizer, builder_options.freeze).freeze # e.g. Path.new(...)
20
21
 
@@ -32,11 +33,14 @@ module Trailblazer
32
33
  activity_adds + merged_adds
33
34
  end
34
35
 
35
- # Stateful helper.
36
+ # DSL method to create a Path within an activity which is embedded.
37
+ #
38
+ # Output(:success) => Path() {}
36
39
  def Path(*args)
37
40
  Activity::DSL::Helper.Path(@normalizer, *args)
38
41
  end
39
42
 
43
+ # Public top-level entry point.
40
44
  def insert(name, task, options, &block)
41
45
  normalizer = options[:normalizer] || @normalizer # DISCUSS: do this at a deeper point?
42
46
 
@@ -50,13 +54,12 @@ module Trailblazer
50
54
  private
51
55
 
52
56
  # Internal top-level entry point to add task(s) and connections.
57
+ # High level interface for DSL calls like ::task or ::step.
53
58
  def insert_element(impl, polarizations, task, local_options, connection_options, sequence_options, &block)
54
59
  adds, *returned_options = Builder.adds_for(polarizations, task, local_options, connection_options, sequence_options, &block)
55
60
  end
56
61
 
57
62
  # @return Adds
58
- # High level interface for DSL calls like ::task or ::step.
59
- # TODO: RETURN ALL OPTIONS
60
63
  def self.adds_for(polarizations, task, local_options, connection_options, sequence_options, &block)
61
64
  # go through all wiring options such as Output()=>:color.
62
65
  polarizations_from_user_options, additional_adds = process_dsl_options(connection_options, local_options, &block)
@@ -75,7 +78,7 @@ module Trailblazer
75
78
  # Low-level interface for DSL calls (e.g. Start, where "you know what you're doing")
76
79
  # @private
77
80
  def self.adds(task, polarizations, options, sequence_options, magnetic_to:nil, id:nil, plus_poles:, **) # DISCUSS: no :id ?
78
- magnetic_to, plus_poles = apply_polarizations(
81
+ magnetic_to, plus_poles = PlusPoles.apply_polarizations(
79
82
  polarizations,
80
83
  magnetic_to,
81
84
  plus_poles,
@@ -88,19 +91,9 @@ module Trailblazer
88
91
  )
89
92
  end
90
93
 
91
- # Called once per DSL method call, e.g. ::step.
92
- #
93
- # The idea is to chain a bunch of PlusPoles transformations (and magnetic_to "transformations")
94
- # for each DSL call, and thus realize things like path+railway+fast_track
95
- def self.apply_polarizations(polarizations, magnetic_to, plus_poles, options)
96
- polarizations.inject([magnetic_to, plus_poles]) do |args, pol|
97
- magnetic, plus_poles = pol.(*args, options)
98
- end
99
- end
100
-
101
94
  def self.Add(id, task, magnetic_to, plus_poles, options, sequence_options)
102
95
  [
103
- [ :add, [id, [ magnetic_to, task, plus_poles.to_a ], sequence_options] ],
96
+ [ :add, [id, [ magnetic_to, task, plus_poles ], sequence_options] ],
104
97
  ]
105
98
  end
106
99
  end # Builder
@@ -1,40 +1,33 @@
1
1
  module Trailblazer
2
2
  module Activity::Magnetic
3
- # The {Normalizer} is called for every DSL call (step/pass/fail etc.) and normalizes/defaults
3
+ # One {Normalizer} instance is called for every DSL call (step/pass/fail etc.) and normalizes/defaults
4
4
  # the user options, such as setting `:id`, connecting the task's outputs or wrapping the user's
5
5
  # task via {TaskBuilder::Binary} in order to translate true/false to `Right` or `Left`.
6
6
  #
7
7
  # The Normalizer sits in the `@builder`, which receives all DSL calls from the Operation subclass.
8
8
  class Normalizer
9
- def self.build(task_builder: Activity::TaskBuilder::Binary, default_plus_poles: Normalizer.InitialPlusPoles(), pipeline: Pipeline, extension:[], **options)
9
+ def self.build(task_builder: Activity::TaskBuilder::Binary, default_outputs: Builder::Path.default_outputs, pipeline: Pipeline, extension:[], **options)
10
10
  return new(
11
- default_plus_poles: default_plus_poles,
12
- extension: extension,
13
- task_builder: task_builder,
14
- pipeline: pipeline,
11
+ default_outputs: default_outputs,
12
+ extension: extension,
13
+ task_builder: task_builder,
14
+ pipeline: pipeline,
15
15
  ), options
16
16
  end
17
17
 
18
- # @private Might be removed.
19
- def self.InitialPlusPoles
20
- Activity::Magnetic::DSL::PlusPoles.new.merge(
21
- Activity.Output(Activity::Right, :success) => nil,
22
- Activity.Output(Activity::Left, :failure) => nil,
23
- )
24
- end
25
-
26
- def initialize(task_builder:, default_plus_poles:, pipeline:, **options)
27
- @task_builder = task_builder
28
- @default_plus_poles = default_plus_poles
29
- @pipeline = pipeline # TODO: test me.
18
+ def initialize(task_builder:, default_outputs:, pipeline:, **options)
19
+ @task_builder = task_builder
20
+ @default_outputs = default_outputs
21
+ @pipeline = pipeline # TODO: test me.
30
22
  freeze
31
23
  end
32
24
 
33
25
  def call(task, options)
34
26
  ctx = {
35
- task: task, options: options,
36
- task_builder: @task_builder,
37
- default_plus_poles: @default_plus_poles,
27
+ task: task,
28
+ options: options,
29
+ task_builder: @task_builder,
30
+ default_outputs: @default_outputs,
38
31
  }
39
32
 
40
33
  signal, (ctx, ) = @pipeline.( [ctx] )
@@ -46,7 +39,7 @@ module Trailblazer
46
39
 
47
40
  # :default_plus_poles is an injectable option.
48
41
  module Pipeline
49
- extend Trailblazer::Activity::Path( normalizer_class: DefaultNormalizer, plus_poles: Builder::Path.default_plus_poles )
42
+ extend Trailblazer::Activity::Path( normalizer_class: DefaultNormalizer, plus_poles: PlusPoles.new.merge( Builder::Path.default_outputs.values ) ) # FIXME: the DefaultNormalizer actually doesn't need Left.
50
43
 
51
44
  def self.split_options( ctx, task:, options:, ** )
52
45
  keywords = extract_dsl_keywords(options)
@@ -84,11 +77,18 @@ module Trailblazer
84
77
  end
85
78
  end
86
79
 
87
- # Merge user options over defaults.
88
- def self.defaultize( ctx, local_options:, default_plus_poles:, ** ) # TODO: test :default_plus_poles
80
+ # :outputs passed: I know what I want to have connected.
81
+ # no :outputs: use default_outputs
82
+ # ALWAYS connect all outputs to their semantic-color.
83
+
84
+ # Create the `plus_poles: <PlusPoles>` tuple where the PlusPoles instance will act as the interface
85
+ # to rewire or add connections for the DSL.
86
+ def self.initialize_plus_poles( ctx, local_options:, default_outputs:, ** )
87
+ outputs = local_options[:outputs] || default_outputs
88
+
89
89
  ctx[:local_options] =
90
90
  {
91
- plus_poles: default_plus_poles,
91
+ plus_poles: PlusPoles.initial(outputs),
92
92
  }
93
93
  .merge(local_options)
94
94
  end
@@ -96,7 +96,7 @@ module Trailblazer
96
96
  task Activity::TaskBuilder::Binary.( method(:normalize_for_macro) ), id: "normalize_for_macro"
97
97
  task Activity::TaskBuilder::Binary.( method(:split_options) ), id: "split_options"
98
98
  task Activity::TaskBuilder::Binary.( method(:normalize_extension_option) ), id: "normalize_extension_option"
99
- task Activity::TaskBuilder::Binary.( method(:defaultize) ), id: "defaultize"
99
+ task Activity::TaskBuilder::Binary.( method(:initialize_plus_poles) ), id: "initialize_plus_poles"
100
100
  # task ->((ctx, _), **) { pp ctx; [Activity::Right, [ctx, _]] }
101
101
  end
102
102
  end # Normalizer
@@ -20,15 +20,16 @@ module Trailblazer
20
20
  return Path, polarizations, task, options, block
21
21
  end
22
22
 
23
-
24
- def self.default_plus_poles
25
- DSL::PlusPoles.new.merge(
26
- Activity.Output( Activity::Right, :success ) => nil
27
- ).freeze
23
+ # @private Might be removed.
24
+ def self.default_outputs
25
+ {
26
+ success: Activity.Output(Activity::Right, :success),
27
+ # failure: Activity.Output(Activity::Left, :failure),
28
+ }
28
29
  end
29
30
 
30
31
  # @return [Adds] list of Adds instances that can be chained or added to an existing sequence.
31
- def self.InitialAdds(track_color:raise, end_semantic:raise, default_plus_poles: self.default_plus_poles, track_end: Activity.End(end_semantic), **)
32
+ def self.InitialAdds(track_color:raise, end_semantic:raise, start_outputs: {success: self.default_outputs[:success]}, track_end: Activity.End(end_semantic), **)
32
33
 
33
34
  builder_options={ track_color: track_color, end_semantic: end_semantic }
34
35
 
@@ -41,7 +42,7 @@ module Trailblazer
41
42
 
42
43
  id: "Start.default",
43
44
  magnetic_to: [],
44
- plus_poles: default_plus_poles
45
+ plus_poles: PlusPoles.initial(start_outputs), # FIXME: this is actually redundant with Normalizer
45
46
  )
46
47
 
47
48
  end_adds = adds(
@@ -59,14 +60,14 @@ module Trailblazer
59
60
  start_adds + end_adds
60
61
  end
61
62
 
62
- def self.TaskPolarizations(track_color:raise, type: :task, **)
63
+ def self.TaskPolarizations(track_color:, type: :task, **)
63
64
  return [EndPolarization.new( track_color: track_color )] if type == :End # DISCUSS: should this dispatch be here?
64
65
 
65
66
  [TaskPolarization.new( track_color: track_color )]
66
67
  end
67
68
 
68
69
  class TaskPolarization
69
- def initialize( track_color:raise )
70
+ def initialize(track_color:)
70
71
  @track_color = track_color
71
72
  end
72
73
 
@@ -22,11 +22,10 @@ module Trailblazer
22
22
  return Railway, Railway.PassPolarizations(@builder_options), task, options, block
23
23
  end
24
24
 
25
- def self.default_plus_poles
26
- DSL::PlusPoles.new.merge(
27
- Activity.Output(Activity::Right, :success) => nil,
28
- Activity.Output(Activity::Left, :failure) => nil,
29
- ).freeze
25
+ def self.default_outputs
26
+ Path.default_outputs.merge(
27
+ :failure => Activity.Output(Activity::Left, :failure),
28
+ )
30
29
  end
31
30
 
32
31
  # Adds the End.failure end to the Path sequence.
@@ -28,30 +28,30 @@ module Trailblazer
28
28
  # options:
29
29
  # { DSL::Output[::Semantic] => target }
30
30
  #
31
- def call(id, options, initial_plus_poles, &block)
31
+ def call(id, options, plus_poles, &block)
32
32
  polarization, adds =
33
33
  options.
34
34
  collect { |key, task|
35
35
  # this method call is the only thing that really matters here. # TODO: make this transformation a bit more obvious.
36
- process_tuple(id, key, task, initial_plus_poles, &block)
36
+ process_tuple(id, key, task, plus_poles, &block)
37
37
  }.
38
38
  inject([[],[]]) { |memo, (polarization, adds)| memo[0]<<polarization; memo[1]<<adds; memo }
39
39
 
40
40
  return polarization, adds.flatten(1)
41
41
  end
42
42
 
43
- def process_tuple(id, output, task, initial_plus_poles, &block)
44
- output = output_for(output, initial_plus_poles) if output.kind_of?(DSL::Output::Semantic)
43
+ def process_tuple(id, output, task, plus_poles, &block)
44
+ output = output_for(output, plus_poles) if output.kind_of?(DSL::Output::Semantic)
45
45
 
46
46
  if task.kind_of?(Activity::End)
47
47
  new_edge = "#{id}-#{output.signal}"
48
48
 
49
49
  [
50
50
  Polarization.new( output: output, color: new_edge ),
51
- [ [:add, [task.instance_variable_get(:@name), [ [new_edge], task, [] ], group: :end]] ]
51
+ [ [:add, [task.to_h[:semantic], [ [new_edge], task, [] ], group: :end]] ]
52
52
  ]
53
53
  elsif task.is_a?(String) # let's say this means an existing step
54
- new_edge = "#{output.signal}-#{task}"
54
+ new_edge = "#{id}-#{output.signal}-#{task}"
55
55
 
56
56
  [
57
57
  Polarization.new( output: output, color: new_edge ),
@@ -0,0 +1,92 @@
1
+ module Trailblazer
2
+ module Activity::Magnetic
3
+ # A plus pole is associating an Output{:signal, :semantic} to a magnetic :color.
4
+ #
5
+ # When it comes to connecting tasks to each other, PlusPoles is the most important object
6
+ # here. When a task is added via the DSL, a PlusPoles is set up, and the DSL adds polarizations
7
+ # from the implementation and from the options (e.g. `Outputs(..) => ..`).
8
+ #
9
+ # These are then finalized and return the effective plus poles
10
+
11
+ # Polarization is one or multiple calls to PlusPoles
12
+
13
+
14
+
15
+
16
+
17
+ # Output(:signal, :semantic) => :color
18
+ # add / merge
19
+ # change existing, => color
20
+ #
21
+ #
22
+ # Produces [ PlusPole, PlusPole, ] via `to_a`.
23
+ #
24
+ # @privat
25
+ # @note This is private until we know what we want.
26
+ class PlusPoles
27
+ def initialize(plus_poles={})
28
+ @plus_poles = plus_poles.freeze
29
+ end
30
+
31
+ # merge( Activity::Magnetic.Output(Right, :success) => :success
32
+ def merge(output_to_color)
33
+ overrides = ::Hash[ output_to_color.collect { |output, color| [ output.semantic, [output, color] ] } ]
34
+ PlusPoles.new(@plus_poles.merge(overrides))
35
+ end
36
+
37
+ def reverse_merge(output_to_color)
38
+ existing_colors = @plus_poles.values.collect { |pole_cfg| pole_cfg.last }
39
+
40
+ # filter all outputs with a color that already exists.
41
+ overrides = output_to_color.find_all { |output, color| !existing_colors.include?(color) }
42
+ merge(overrides)
43
+ end
44
+
45
+ def reconnect(semantic_to_color)
46
+ ary = semantic_to_color.collect do |semantic, color|
47
+ existing_output, _ = @plus_poles[semantic]
48
+
49
+ next unless existing_output
50
+
51
+ [ Activity.Output(existing_output.signal, existing_output.semantic), color ]
52
+ end
53
+
54
+ merge( ::Hash[ary.compact] )
55
+ end
56
+
57
+ # Compile one {PlusPoles} instance from all a sequence of {Polarization}s.
58
+ # This is usually called once per `step` DSL call.
59
+ #
60
+ # @api private
61
+ def self.apply_polarizations(polarizations, magnetic_to, plus_poles, options)
62
+ magnetic_to, plus_poles = polarizations.inject([magnetic_to, plus_poles]) do |args, pol|
63
+ magnetic_to, plus_poles = pol.(*args, options)
64
+ end
65
+
66
+ return magnetic_to, plus_poles.to_a
67
+ end
68
+
69
+ # The DSL is a series of transformations that yield in tasks with several PlusPole instances each.
70
+ #
71
+ # @api private
72
+ def to_a
73
+ @plus_poles.values.collect { |output, color| PlusPole.new(output, color) }
74
+ end
75
+
76
+ # Builds PlusPoles from { semantic => Output }, which, surprisingly, is exactly what Activity::outputs looks like.
77
+ # The plus pole's color is set to the output's semantic.
78
+ def self.from_outputs(outputs)
79
+ ary = outputs.collect { |semantic, output| [ output, semantic ] }
80
+
81
+ new.merge(::Hash[ary])
82
+ end
83
+
84
+ # FIXME: should this be a hash or whatever?
85
+ #
86
+ # @return Hash All {Output}s mapped to their semantic: `{ Output(Right, :success) => :success }`
87
+ def self.initial(outputs)
88
+ new.merge(Hash[ outputs.collect { |semantic, output| [output, semantic] } ])
89
+ end
90
+ end
91
+ end
92
+ end
@@ -1,6 +1,6 @@
1
1
  module Trailblazer
2
2
  class Activity < Module # End event is just another callable task.
3
- # Builds an Activity::End instance.
3
+ # Builds an {Activity::End} instance.
4
4
  def self.End(semantic)
5
5
  End.new(semantic: semantic)
6
6
  end
@@ -48,6 +48,7 @@
48
48
  # semantic: the original "semantic" or role of the signal, such as :success. This usually comes from the activity hosting this output.
49
49
  Output = Struct.new(:signal, :semantic)
50
50
 
51
+ # Builds an {Activity::Output} instance.
51
52
  def self.Output(signal, color)
52
53
  Output.new(signal, color).freeze
53
54
  end
@@ -33,6 +33,11 @@ module Trailblazer
33
33
 
34
34
  [ direction, [ options, *args ], **circuit_args ]
35
35
  end
36
+
37
+ def inspect
38
+ %{#<Trailblazer::Activity::TaskBuilder::Task user_proc=#{@user_proc}>}
39
+ end
40
+ alias_method :to_s, :inspect
36
41
  end
37
42
  end
38
43
  end
@@ -1,4 +1,5 @@
1
- class Trailblazer::Activity < Module
1
+ module Trailblazer
2
+ class Activity < Module
2
3
  #
3
4
  # Example with tracing:
4
5
  #
@@ -8,39 +9,44 @@ class Trailblazer::Activity < Module
8
9
  # |-- Call (call actual task) id: "task_wrap.call_task"
9
10
  # |-- Trace.capture_return [optional]
10
11
  # |-- Wrap::End
11
- module TaskWrap
12
- # The actual activity that implements the taskWrap.
13
- def self.initial_activity
14
- Module.new do
15
- extend Trailblazer::Activity::Path( name: "taskWrap", normalizer_class: Magnetic::DefaultNormalizer )
12
+ module TaskWrap
13
+ # The actual activity that implements the taskWrap.
14
+ def self.initial_activity
15
+ Module.new do
16
+ extend Trailblazer::Activity::Path(
17
+ name: "taskWrap",
18
+ normalizer_class: Magnetic::DefaultNormalizer,
19
+ plus_poles: Magnetic::PlusPoles.initial( :success => Magnetic::Builder::Path.default_outputs[:success] ) # DefaultNormalizer doesn't give us default PlusPoles.
20
+ )
16
21
 
17
- task TaskWrap.method(:call_task), id: "task_wrap.call_task" # ::call_task is defined in task_wrap/call_task.
22
+ task TaskWrap.method(:call_task), id: "task_wrap.call_task" # ::call_task is defined in task_wrap/call_task.
23
+ end
18
24
  end
19
- end
20
-
21
- # Compute runtime arguments necessary to execute a taskWrap per task of the activity.
22
- def self.arguments_for_call(activity, (options, flow_options), **circuit_options)
23
- circuit_options = circuit_options.merge(
24
- runner: TaskWrap::Runner,
25
- wrap_runtime: circuit_options[:wrap_runtime] || {},
26
- wrap_static: activity[:wrap_static] || {},
27
- )
28
25
 
29
- return activity, [ options, flow_options ], circuit_options
30
- end
31
-
32
- module NonStatic
26
+ # Compute runtime arguments necessary to execute a taskWrap per task of the activity.
33
27
  def self.arguments_for_call(activity, (options, flow_options), **circuit_options)
34
28
  circuit_options = circuit_options.merge(
35
29
  runner: TaskWrap::Runner,
36
- wrap_runtime: circuit_options[:wrap_runtime] || {}, # FIXME:this sucks. (was:) this overwrites wrap_runtime from outside.
37
- wrap_static: ::Hash.new(TaskWrap.initial_activity), # add a default static wrap.
30
+ wrap_runtime: circuit_options[:wrap_runtime] || {},
31
+ wrap_static: activity[:wrap_static] || {},
38
32
  )
39
33
 
40
34
  return activity, [ options, flow_options ], circuit_options
41
35
  end
42
- end
43
36
 
44
- # better: MyClass < Activity(TaskWrap, ...)
37
+ module NonStatic
38
+ def self.arguments_for_call(activity, (options, flow_options), **circuit_options)
39
+ circuit_options = circuit_options.merge(
40
+ runner: TaskWrap::Runner,
41
+ wrap_runtime: circuit_options[:wrap_runtime] || {}, # FIXME:this sucks. (was:) this overwrites wrap_runtime from outside.
42
+ wrap_static: ::Hash.new(TaskWrap.initial_activity), # add a default static wrap.
43
+ )
44
+
45
+ return activity, [ options, flow_options ], circuit_options
46
+ end
47
+ end
48
+
49
+ # better: MyClass < Activity(TaskWrap, ...)
50
+ end
45
51
  end
46
52
  end
@@ -1,5 +1,5 @@
1
1
  module Trailblazer
2
2
  class Activity < Module
3
- VERSION = "0.4.2"
3
+ VERSION = "0.4.3"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trailblazer-activity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-01-24 00:00:00.000000000 Z
11
+ date: 2018-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hirb
@@ -112,6 +112,7 @@ files:
112
112
  - NOTES_
113
113
  - README.md
114
114
  - Rakefile
115
+ - inspeccccccccct.rb
115
116
  - lib/trailblazer-activity.rb
116
117
  - lib/trailblazer/activity.rb
117
118
  - lib/trailblazer/activity/config.rb
@@ -121,6 +122,7 @@ files:
121
122
  - lib/trailblazer/activity/implementation/fast_track.rb
122
123
  - lib/trailblazer/activity/implementation/interface.rb
123
124
  - lib/trailblazer/activity/implementation/path.rb
125
+ - lib/trailblazer/activity/implementation/plan.rb
124
126
  - lib/trailblazer/activity/implementation/railway.rb
125
127
  - lib/trailblazer/activity/introspect.rb
126
128
  - lib/trailblazer/activity/magnetic.rb
@@ -131,11 +133,11 @@ files:
131
133
  - lib/trailblazer/activity/magnetic/builder/path.rb
132
134
  - lib/trailblazer/activity/magnetic/builder/railway.rb
133
135
  - lib/trailblazer/activity/magnetic/dsl.rb
134
- - lib/trailblazer/activity/magnetic/dsl/alterations.rb
135
- - lib/trailblazer/activity/magnetic/dsl/plus_poles.rb
136
136
  - lib/trailblazer/activity/magnetic/finalizer.rb
137
137
  - lib/trailblazer/activity/magnetic/generate.rb
138
138
  - lib/trailblazer/activity/magnetic/merge.rb
139
+ - lib/trailblazer/activity/magnetic/structure/alterations.rb
140
+ - lib/trailblazer/activity/magnetic/structure/plus_poles.rb
139
141
  - lib/trailblazer/activity/present.rb
140
142
  - lib/trailblazer/activity/schema/dependencies.rb
141
143
  - lib/trailblazer/activity/schema/sequence.rb
@@ -1,59 +0,0 @@
1
- module Trailblazer
2
- module Activity::Magnetic
3
- module DSL
4
- # Output(:signal, :semantic) => :color
5
- # add / merge
6
- # change existing, => color
7
- #
8
- # Mutable DSL datastructure for managing all PlusPoles for a particular task.
9
- #
10
- # Produces [ PlusPole, PlusPole, ] via `to_a`.
11
- #
12
- # @privat
13
- # @note This is private until we know what we want.
14
- class PlusPoles
15
- def initialize(plus_poles={})
16
- @plus_poles = plus_poles.freeze
17
- end
18
-
19
- # merge( Activity::Magnetic.Output(Right, :success) => :success
20
- def merge(output_to_color)
21
- overrides = ::Hash[ output_to_color.collect { |output, color| [ output.semantic, [output, color] ] } ]
22
- PlusPoles.new(@plus_poles.merge(overrides))
23
- end
24
-
25
- def reverse_merge(output_to_color)
26
- existing_colors = @plus_poles.values.collect { |pole_cfg| pole_cfg.last }
27
-
28
- overrides = output_to_color.find_all { |output, color| !existing_colors.include?(color) } # filter all outputs with a color that already exists.
29
- merge(overrides)
30
- end
31
-
32
- def reconnect(semantic_to_color)
33
- ary = semantic_to_color.collect do |semantic, color|
34
- existing_output, _ = @plus_poles[semantic]
35
-
36
- next unless existing_output
37
-
38
- [ Activity.Output(existing_output.signal, existing_output.semantic), color ]
39
- end
40
-
41
- merge( ::Hash[ary.compact] )
42
- end
43
-
44
- # The DSL is a series of transformations that yield in tasks with several PlusPole instances each.
45
- def to_a
46
- @plus_poles.values.collect { |output, color| PlusPole.new(output, color) }
47
- end
48
-
49
- # Builds PlusPoles from { semantic => Output }, which, surprisingly, is exactly what Activity::outputs looks like.
50
- # The plus pole's color is set to the output's semantic.
51
- def self.from_outputs(outputs)
52
- ary = outputs.collect { |semantic, output| [ output, semantic ] }
53
-
54
- new.merge(::Hash[ary])
55
- end
56
- end
57
- end
58
- end
59
- end