trailblazer-future 2.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +6 -0
- data/CHANGES.md +4 -0
- data/LICENSE.txt +9 -0
- data/README.md +48 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/gems.rb +3 -0
- data/lib/trailblazer/future.rb +9 -0
- data/lib/trailblazer/future/version.rb +5 -0
- data/lib/trailblazer/v2_1/activity.rb +123 -0
- data/lib/trailblazer/v2_1/activity/config.rb +37 -0
- data/lib/trailblazer/v2_1/activity/dsl/add_task.rb +22 -0
- data/lib/trailblazer/v2_1/activity/dsl/helper.rb +68 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic.rb +36 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder.rb +101 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder/default_normalizer.rb +26 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder/fast_track.rb +118 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder/normalizer.rb +113 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder/path.rb +105 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder/railway.rb +97 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder/state.rb +58 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/finalizer.rb +51 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/generate.rb +62 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/merge.rb +16 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/process_options.rb +76 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/structure/alterations.rb +44 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/structure/plus_poles.rb +85 -0
- data/lib/trailblazer/v2_1/activity/dsl/magnetic/structure/polarization.rb +23 -0
- data/lib/trailblazer/v2_1/activity/dsl/record.rb +11 -0
- data/lib/trailblazer/v2_1/activity/dsl/schema/dependencies.rb +46 -0
- data/lib/trailblazer/v2_1/activity/dsl/schema/sequence.rb +46 -0
- data/lib/trailblazer/v2_1/activity/dsl/strategy/build_state.rb +32 -0
- data/lib/trailblazer/v2_1/activity/dsl/strategy/fast_track.rb +24 -0
- data/lib/trailblazer/v2_1/activity/dsl/strategy/path.rb +26 -0
- data/lib/trailblazer/v2_1/activity/dsl/strategy/plan.rb +36 -0
- data/lib/trailblazer/v2_1/activity/dsl/strategy/railway.rb +23 -0
- data/lib/trailblazer/v2_1/activity/interface.rb +16 -0
- data/lib/trailblazer/v2_1/activity/introspect.rb +167 -0
- data/lib/trailblazer/v2_1/activity/present.rb +95 -0
- data/lib/trailblazer/v2_1/activity/structures.rb +57 -0
- data/lib/trailblazer/v2_1/activity/task_builder.rb +41 -0
- data/lib/trailblazer/v2_1/activity/task_wrap.rb +40 -0
- data/lib/trailblazer/v2_1/activity/task_wrap/call_task.rb +19 -0
- data/lib/trailblazer/v2_1/activity/task_wrap/merge.rb +23 -0
- data/lib/trailblazer/v2_1/activity/task_wrap/runner.rb +62 -0
- data/lib/trailblazer/v2_1/activity/task_wrap/trace.rb +44 -0
- data/lib/trailblazer/v2_1/activity/task_wrap/variable_mapping.rb +162 -0
- data/lib/trailblazer/v2_1/activity/testing.rb +32 -0
- data/lib/trailblazer/v2_1/activity/trace.rb +97 -0
- data/lib/trailblazer/v2_1/circuit.rb +71 -0
- data/lib/trailblazer/v2_1/container_chain.rb +45 -0
- data/lib/trailblazer/v2_1/context.rb +79 -0
- data/lib/trailblazer/v2_1/deprecation/call.rb +46 -0
- data/lib/trailblazer/v2_1/deprecation/context.rb +43 -0
- data/lib/trailblazer/v2_1/dsl.rb +47 -0
- data/lib/trailblazer/v2_1/macro.rb +11 -0
- data/lib/trailblazer/v2_1/macro/contract.rb +5 -0
- data/lib/trailblazer/v2_1/operation.rb +91 -0
- data/lib/trailblazer/v2_1/operation/auto_inject.rb +47 -0
- data/lib/trailblazer/v2_1/operation/callable.rb +42 -0
- data/lib/trailblazer/v2_1/operation/class_dependencies.rb +25 -0
- data/lib/trailblazer/v2_1/operation/contract.rb +61 -0
- data/lib/trailblazer/v2_1/operation/deprecated_macro.rb +19 -0
- data/lib/trailblazer/v2_1/operation/deprecations.rb +21 -0
- data/lib/trailblazer/v2_1/operation/guard.rb +18 -0
- data/lib/trailblazer/v2_1/operation/heritage.rb +30 -0
- data/lib/trailblazer/v2_1/operation/inject.rb +36 -0
- data/lib/trailblazer/v2_1/operation/inspect.rb +79 -0
- data/lib/trailblazer/v2_1/operation/model.rb +50 -0
- data/lib/trailblazer/v2_1/operation/module.rb +29 -0
- data/lib/trailblazer/v2_1/operation/nested.rb +98 -0
- data/lib/trailblazer/v2_1/operation/persist.rb +14 -0
- data/lib/trailblazer/v2_1/operation/policy.rb +44 -0
- data/lib/trailblazer/v2_1/operation/public_call.rb +55 -0
- data/lib/trailblazer/v2_1/operation/pundit.rb +38 -0
- data/lib/trailblazer/v2_1/operation/railway.rb +32 -0
- data/lib/trailblazer/v2_1/operation/railway/fast_track.rb +13 -0
- data/lib/trailblazer/v2_1/operation/railway/macaroni.rb +23 -0
- data/lib/trailblazer/v2_1/operation/railway/normalizer.rb +58 -0
- data/lib/trailblazer/v2_1/operation/railway/task_builder.rb +37 -0
- data/lib/trailblazer/v2_1/operation/rescue.rb +42 -0
- data/lib/trailblazer/v2_1/operation/responder.rb +18 -0
- data/lib/trailblazer/v2_1/operation/result.rb +30 -0
- data/lib/trailblazer/v2_1/operation/test.rb +17 -0
- data/lib/trailblazer/v2_1/operation/trace.rb +46 -0
- data/lib/trailblazer/v2_1/operation/validate.rb +76 -0
- data/lib/trailblazer/v2_1/operation/wrap.rb +83 -0
- data/lib/trailblazer/v2_1/option.rb +78 -0
- data/lib/trailblazer/v2_1/rails.rb +12 -0
- data/lib/trailblazer/v2_1/rails/cell.rb +22 -0
- data/lib/trailblazer/v2_1/rails/controller.rb +66 -0
- data/lib/trailblazer/v2_1/rails/form.rb +21 -0
- data/lib/trailblazer/v2_1/rails/railtie.rb +31 -0
- data/lib/trailblazer/v2_1/rails/railtie/extend_application_controller.rb +28 -0
- data/lib/trailblazer/v2_1/rails/railtie/loader.rb +58 -0
- data/lib/trailblazer/v2_1/rails/test/integration.rb +6 -0
- data/lib/trailblazer/v2_1/versions.txt +7 -0
- data/test/rails5.0/.gitignore +17 -0
- data/test/rails5.0/Gemfile +21 -0
- data/test/rails5.0/Rakefile +3 -0
- data/test/rails5.0/app/concepts/artist/cell/dashboard.rb +7 -0
- data/test/rails5.0/app/concepts/artist/cell/show.rb +4 -0
- data/test/rails5.0/app/concepts/artist/view/dashboard.erb +4 -0
- data/test/rails5.0/app/concepts/artist/view/show.erb +1 -0
- data/test/rails5.0/app/concepts/params/operation/with_args.rb +5 -0
- data/test/rails5.0/app/concepts/song/contract/form.rb +6 -0
- data/test/rails5.0/app/concepts/song/operation/create.rb +15 -0
- data/test/rails5.0/app/concepts/song/operation/show.rb +3 -0
- data/test/rails5.0/app/concepts/song/operation/update.rb +15 -0
- data/test/rails5.0/app/controllers/application_controller.rb +46 -0
- data/test/rails5.0/app/controllers/args_controller.rb +5 -0
- data/test/rails5.0/app/controllers/artists_controller.rb +24 -0
- data/test/rails5.0/app/controllers/params_controller.rb +11 -0
- data/test/rails5.0/app/controllers/songs_controller.rb +35 -0
- data/test/rails5.0/app/models/artist.rb +2 -0
- data/test/rails5.0/app/models/song.rb +2 -0
- data/test/rails5.0/app/views/args/with_args.html.erb +1 -0
- data/test/rails5.0/app/views/layouts/application.html.erb +2 -0
- data/test/rails5.0/app/views/songs/edit.html.erb +4 -0
- data/test/rails5.0/app/views/songs/new.html.erb +5 -0
- data/test/rails5.0/app/views/songs/new_with_result.html.erb +3 -0
- data/test/rails5.0/app/views/songs/show.html.erb +3 -0
- data/test/rails5.0/bin/bundle +3 -0
- data/test/rails5.0/bin/rails +4 -0
- data/test/rails5.0/bin/rake +4 -0
- data/test/rails5.0/bin/setup +29 -0
- data/test/rails5.0/config.ru +4 -0
- data/test/rails5.0/config/application.rb +25 -0
- data/test/rails5.0/config/boot.rb +3 -0
- data/test/rails5.0/config/database.yml +21 -0
- data/test/rails5.0/config/environment.rb +5 -0
- data/test/rails5.0/config/environments/development.rb +41 -0
- data/test/rails5.0/config/environments/test.rb +42 -0
- data/test/rails5.0/config/initializers/assets.rb +11 -0
- data/test/rails5.0/config/initializers/backtrace_silencers.rb +7 -0
- data/test/rails5.0/config/initializers/cookies_serializer.rb +3 -0
- data/test/rails5.0/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/rails5.0/config/initializers/inflections.rb +16 -0
- data/test/rails5.0/config/initializers/mime_types.rb +4 -0
- data/test/rails5.0/config/initializers/session_store.rb +3 -0
- data/test/rails5.0/config/initializers/wrap_parameters.rb +14 -0
- data/test/rails5.0/config/locales/en.yml +23 -0
- data/test/rails5.0/config/routes.rb +15 -0
- data/test/rails5.0/config/secrets.yml +17 -0
- data/test/rails5.0/db/migrate/20161122145124_create_songs.rb +8 -0
- data/test/rails5.0/db/schema.rb +19 -0
- data/test/rails5.0/log/.keep +0 -0
- data/test/rails5.0/test/concepts/song/operation/create_test.rb +11 -0
- data/test/rails5.0/test/concepts/song/operation/update_test.rb +34 -0
- data/test/rails5.0/test/integration/.keep +0 -0
- data/test/rails5.0/test/integration/args_controller_test.rb +8 -0
- data/test/rails5.0/test/integration/artists_controller_test.rb +28 -0
- data/test/rails5.0/test/integration/params_controller_test.rb +8 -0
- data/test/rails5.0/test/integration/songs_controller_test.rb +40 -0
- data/test/rails5.0/test/test_helper.rb +7 -0
- data/test/test_helper.rb +5 -0
- data/trailblazer-future.gemspec +25 -0
- metadata +246 -0
@@ -0,0 +1,97 @@
|
|
1
|
+
module Trailblazer::V2_1
|
2
|
+
module Activity::Magnetic
|
3
|
+
class Builder
|
4
|
+
class Railway < Builder
|
5
|
+
def self.for(normalizer, builder_options={}) # Build the Builder.
|
6
|
+
Activity::Magnetic::Builder(
|
7
|
+
Railway,
|
8
|
+
normalizer,
|
9
|
+
{ track_color: :success, end_semantic: :success, failure_color: :failure }.merge( builder_options )
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Adds the End.failure end to the Path sequence.
|
14
|
+
# @return [Adds] list of Adds instances that can be chained or added to an existing sequence.
|
15
|
+
def self.InitialAdds(failure_color:raise, failure_end: Activity.End(failure_color), **builder_options)
|
16
|
+
path_adds = Path.InitialAdds(**builder_options)
|
17
|
+
|
18
|
+
end_adds = adds(
|
19
|
+
failure_end,
|
20
|
+
|
21
|
+
Path::EndEventPolarizations(builder_options),
|
22
|
+
|
23
|
+
{},
|
24
|
+
{ group: :end },
|
25
|
+
|
26
|
+
magnetic_to: [failure_color],
|
27
|
+
id: "End.#{failure_color}",
|
28
|
+
plus_poles: {},
|
29
|
+
)
|
30
|
+
|
31
|
+
path_adds + end_adds
|
32
|
+
end
|
33
|
+
|
34
|
+
# ONLY JOB: magnetic_to and Outputs ("Polarization") via PlusPoles.merge
|
35
|
+
def self.StepPolarizations(**options)
|
36
|
+
[
|
37
|
+
*Path.TaskPolarizations(options),
|
38
|
+
StepPolarization.new(options)
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.PassPolarizations(options)
|
43
|
+
[
|
44
|
+
Railway::PassPolarization.new( options )
|
45
|
+
]
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.FailPolarizations(options)
|
49
|
+
[
|
50
|
+
Railway::FailPolarization.new( options )
|
51
|
+
]
|
52
|
+
end
|
53
|
+
|
54
|
+
class StepPolarization
|
55
|
+
def initialize(track_color: :success, failure_color: :failure, **o)
|
56
|
+
@track_color, @failure_color = track_color, failure_color
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the polarization for a DSL call. Takes care of user options such as :magnetic_to.
|
60
|
+
def call(magnetic_to, plus_poles, options)
|
61
|
+
[
|
62
|
+
magnetic_to || default_magnetic_to,
|
63
|
+
plus_poles_for(plus_poles, options),
|
64
|
+
]
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def plus_poles_for(plus_poles, options)
|
70
|
+
plus_poles.reconnect( :failure => @failure_color )
|
71
|
+
end
|
72
|
+
|
73
|
+
def default_magnetic_to
|
74
|
+
[@track_color]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class PassPolarization < StepPolarization
|
79
|
+
def plus_poles_for(plus_poles, options)
|
80
|
+
plus_poles.reconnect( :failure => @track_color, :success => @track_color )
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class FailPolarization < StepPolarization
|
85
|
+
def default_magnetic_to
|
86
|
+
[@failure_color]
|
87
|
+
end
|
88
|
+
|
89
|
+
def plus_poles_for(plus_poles, options)
|
90
|
+
plus_poles.reconnect( :failure => @failure_color, :success => @failure_color )
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end # Railway
|
95
|
+
end # Builder
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Trailblazer::V2_1
|
2
|
+
class Activity::Magnetic::Builder
|
3
|
+
# Maintain Builder instance plus Adds/Process/Outputs as immutable objects.
|
4
|
+
module State
|
5
|
+
def self.build(builder_class, normalizer, builder_options)
|
6
|
+
builder, adds = builder_class.for(normalizer, builder_options) # e.g. Path.for(...) which creates a Builder::Path instance.
|
7
|
+
|
8
|
+
recompile(builder.freeze, adds.freeze)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.add(builder, adds, strategy, polarizer, *args, &block)
|
12
|
+
new_adds, *returned_options = builder.insert(strategy, polarizer, *args, &block) # TODO: move that out of here.
|
13
|
+
|
14
|
+
adds = adds + new_adds
|
15
|
+
|
16
|
+
recompile(builder, adds.freeze, returned_options)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# @return {builder, Adds, Process, outputs}, returned_options
|
22
|
+
def self.recompile(builder, adds, *args)
|
23
|
+
circuit, outputs = recompile_circuit(adds)
|
24
|
+
|
25
|
+
return builder, adds, circuit.freeze, outputs.freeze, *args
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.recompile_circuit(adds)
|
29
|
+
circuit, outputs = Recompile.( adds )
|
30
|
+
end
|
31
|
+
|
32
|
+
module Recompile
|
33
|
+
# Recompile the circuit and outputs from the {ADDS} instance that collects circuit tasks and connections.
|
34
|
+
#
|
35
|
+
# @return [Process, Hash] The {Process} instance and its outputs hash.
|
36
|
+
def self.call(adds)
|
37
|
+
circuit, end_events = Finalizer.(adds)
|
38
|
+
outputs = recompile_outputs(end_events)
|
39
|
+
|
40
|
+
return circuit, outputs
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def self.recompile_outputs(end_events)
|
46
|
+
ary = end_events.collect do |evt|
|
47
|
+
[
|
48
|
+
semantic = evt.to_h[:semantic],
|
49
|
+
Activity::Output(evt, semantic)
|
50
|
+
]
|
51
|
+
end
|
52
|
+
|
53
|
+
::Hash[ ary ]
|
54
|
+
end
|
55
|
+
end # Recompile
|
56
|
+
end # State
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Trailblazer::V2_1
|
2
|
+
module Activity::Magnetic
|
3
|
+
class Builder
|
4
|
+
module Finalizer
|
5
|
+
|
6
|
+
def self.call(adds)
|
7
|
+
tripletts = adds_to_tripletts(adds)
|
8
|
+
|
9
|
+
circuit_hash = tripletts_to_circuit_hash( tripletts )
|
10
|
+
|
11
|
+
circuit_hash_to_process( circuit_hash )
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.adds_to_tripletts(adds)
|
15
|
+
alterations = adds_to_alterations(adds)
|
16
|
+
|
17
|
+
alterations.to_a
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.adds_to_alterations(adds)
|
21
|
+
alterations = DSL::Alterations.new
|
22
|
+
|
23
|
+
adds = adds.compact # TODO: test me explicitly, and where does this come from anyway?
|
24
|
+
|
25
|
+
adds.each { |method, cfg| alterations.send( method, *cfg ) }
|
26
|
+
|
27
|
+
alterations
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.tripletts_to_circuit_hash(tripletts)
|
31
|
+
Activity::Magnetic::Generate.( tripletts )
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.circuit_hash_to_process(circuit_hash)
|
35
|
+
end_events = end_events_for(circuit_hash)
|
36
|
+
|
37
|
+
return Circuit.new(circuit_hash, end_events, start_task: circuit_hash.keys.first), end_events
|
38
|
+
end
|
39
|
+
|
40
|
+
# Find all end events that don't have outgoing connections.
|
41
|
+
def self.end_events_for(circuit_hash)
|
42
|
+
ary = circuit_hash.collect do |task, connections|
|
43
|
+
task.kind_of?(Activity::End) && connections.empty? ? task : nil
|
44
|
+
end
|
45
|
+
|
46
|
+
ary.compact
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Trailblazer::V2_1
|
2
|
+
module Activity::Magnetic
|
3
|
+
# Transforms an array of {Triplett}s into a circuit hash.
|
4
|
+
module Generate
|
5
|
+
Line = Struct.new(:source, :output)
|
6
|
+
MinusPole = Struct.new(:color)
|
7
|
+
|
8
|
+
class OpenLines
|
9
|
+
def initialize
|
10
|
+
@arr = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def pop(signal, &block)
|
14
|
+
lines = @arr.find_all { |line| line.output.color == signal }
|
15
|
+
@arr -= lines
|
16
|
+
|
17
|
+
lines.each(&block)
|
18
|
+
lines.any?
|
19
|
+
end
|
20
|
+
|
21
|
+
def <<((node, output))
|
22
|
+
@arr << Line.new(node, output)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.call(tasks)
|
27
|
+
open_plus_poles = OpenLines.new
|
28
|
+
open_minus_poles = OpenLines.new
|
29
|
+
circuit_hash = {}
|
30
|
+
|
31
|
+
tasks.each do |(magnetic_to, node, outputs)|
|
32
|
+
circuit_hash[ node ] ||= {} # DISCUSS: or needed?
|
33
|
+
|
34
|
+
magnetic_to.each do |edge_color| # minus poles
|
35
|
+
open_plus_poles.pop(edge_color) do |line|
|
36
|
+
connect( circuit_hash, line.source, line.output.signal, node )
|
37
|
+
end and next
|
38
|
+
|
39
|
+
# only run when there were no open_minus_poles
|
40
|
+
open_minus_poles << [node, MinusPole.new(edge_color)] # open inputs on a node, waiting to be connected.
|
41
|
+
end
|
42
|
+
|
43
|
+
outputs.each do |output|
|
44
|
+
open_minus_poles.pop(output.color) do |line|
|
45
|
+
connect( circuit_hash, node, output.signal, line.source )
|
46
|
+
end and next
|
47
|
+
|
48
|
+
# only run when there were no open_plus_poles
|
49
|
+
open_plus_poles << [node, output]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
circuit_hash
|
54
|
+
end
|
55
|
+
|
56
|
+
# plus minus
|
57
|
+
def self.connect(circuit_hash, source, signal, target)
|
58
|
+
circuit_hash[ source ][ signal ] = target
|
59
|
+
end
|
60
|
+
end # Magnetic
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Trailblazer::V2_1::Activity < Module
|
2
|
+
module Magnetic
|
3
|
+
module Merge
|
4
|
+
def merge!(merged)
|
5
|
+
merged[:record].each do |key, args|
|
6
|
+
dsl_method, *args = args
|
7
|
+
|
8
|
+
return send( dsl_method, args[0], args[1], &args[2] ) if args[2]
|
9
|
+
send( dsl_method, args[0], args[1] )
|
10
|
+
end
|
11
|
+
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Trailblazer::V2_1
|
2
|
+
module Activity::Magnetic
|
3
|
+
module DSL
|
4
|
+
# This module only processes additional "wiring" options from the DSL calls
|
5
|
+
# Output(:success) => End("my.new")
|
6
|
+
#
|
7
|
+
# Returns PlusPoles and additional sequence alterations.
|
8
|
+
module ProcessOptions
|
9
|
+
module_function
|
10
|
+
|
11
|
+
# Output => target (End/"id"/:color)
|
12
|
+
# @return [PlusPole]
|
13
|
+
# @return additional alterations
|
14
|
+
#
|
15
|
+
# options:
|
16
|
+
# { DSL::Output[::Semantic] => target }
|
17
|
+
#
|
18
|
+
def call(id, options, plus_poles, &block)
|
19
|
+
polarization, adds =
|
20
|
+
options.
|
21
|
+
collect { |key, task|
|
22
|
+
# this method call is the only thing that really matters here. # TODO: make this transformation a bit more obvious.
|
23
|
+
process_tuple(id, key, task, plus_poles, &block)
|
24
|
+
}.
|
25
|
+
inject([[],[]]) { |memo, (polarization, adds)| memo[0]<<polarization; memo[1]<<adds; memo }
|
26
|
+
|
27
|
+
return polarization, adds.flatten(1)
|
28
|
+
end
|
29
|
+
|
30
|
+
def process_tuple(id, output, task, plus_poles, &block)
|
31
|
+
output = output_for(output, plus_poles) if output.kind_of?(Activity::DSL::OutputSemantic)
|
32
|
+
|
33
|
+
if task.kind_of?(Activity::End)
|
34
|
+
# raise %{An end event with semantic `#{task.to_h[:semantic]}` has already been added. Please use an ID reference: `=> "End.#{task.to_h[:semantic]}"`} if
|
35
|
+
new_edge = "#{id}-#{output.signal}"
|
36
|
+
|
37
|
+
[
|
38
|
+
Polarization.new( output: output, color: new_edge ),
|
39
|
+
[ [:add, [task.to_h[:semantic], [ [new_edge], task, [] ], group: :end]] ]
|
40
|
+
]
|
41
|
+
# procs come from DSL calls such as `Path() do ... end`.
|
42
|
+
elsif task.is_a?(Proc)
|
43
|
+
start_color, activity = task.(block)
|
44
|
+
|
45
|
+
adds = activity.to_h[:adds]
|
46
|
+
|
47
|
+
[
|
48
|
+
Polarization.new( output: output, color: start_color ),
|
49
|
+
# TODO: this is a pseudo-"merge" and should be public API at some point.
|
50
|
+
# TODO: we also need to merge all the other states such as debug.
|
51
|
+
adds[1..-1] # drop start
|
52
|
+
]
|
53
|
+
elsif task.is_a?(Activity::DSL::Track) # An additional plus polarization. Example: Output => :success
|
54
|
+
[
|
55
|
+
Polarization.new( output: output, color: task.color )
|
56
|
+
]
|
57
|
+
else # ID: existing step
|
58
|
+
new_edge = "#{id}-#{output.signal}-#{task}" # edge from <id> to <target>
|
59
|
+
|
60
|
+
[
|
61
|
+
Polarization.new( output: output, color: new_edge ),
|
62
|
+
[[ :magnetic_to, [ task, [new_edge] ] ]], # mark target (`task`) as magnetic to the new edge.
|
63
|
+
]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param semantic DSL::Output::Semantic
|
68
|
+
def output_for(semantic, plus_poles)
|
69
|
+
# DISCUSS: review PlusPoles#[]
|
70
|
+
output, _ = plus_poles.instance_variable_get(:@plus_poles)[semantic.value]
|
71
|
+
output or raise("Couldn't find existing output for `#{semantic.value.inspect}`.")
|
72
|
+
end
|
73
|
+
end # OptionsProcessing
|
74
|
+
end # DSL
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Trailblazer::V2_1
|
2
|
+
module Activity::Magnetic
|
3
|
+
module DSL
|
4
|
+
# works on a generic Dependencies structure that has no knowledge of magnetism.
|
5
|
+
class Alterations
|
6
|
+
def initialize
|
7
|
+
@groups = Activity::Schema::Dependencies.new
|
8
|
+
@future_magnetic_to = {} # DISCUSS: future - should it be here?
|
9
|
+
end
|
10
|
+
|
11
|
+
def add(id, options, **sequence_options)
|
12
|
+
@groups.add(id, options, **sequence_options)
|
13
|
+
|
14
|
+
# DISCUSS: future - should it be here?
|
15
|
+
if magnetic_to = @future_magnetic_to.delete(id)
|
16
|
+
magnetic_to( id, magnetic_to )
|
17
|
+
end
|
18
|
+
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
# make `id` magnetic_to
|
23
|
+
def magnetic_to(id, magnetic_to)
|
24
|
+
group, index = @groups.find(id) # this can be a future task!
|
25
|
+
|
26
|
+
unless group # DISCUSS: future - should it be here?
|
27
|
+
@future_magnetic_to[id] = magnetic_to
|
28
|
+
return
|
29
|
+
end
|
30
|
+
|
31
|
+
arr = group[index].configuration.dup
|
32
|
+
|
33
|
+
arr[0] = arr[0] + magnetic_to
|
34
|
+
group.add(id, arr, replace: id)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns array of tripletts.
|
38
|
+
def to_a
|
39
|
+
@groups.to_a
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end # DSL
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Trailblazer::V2_1
|
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
|
+
# FIXME: should this be a hash or whatever?
|
77
|
+
#
|
78
|
+
# @return Hash All {Output}s mapped to their (guessed) semantic: `{ Output(Right, :success) => :success }`
|
79
|
+
def self.initial(outputs)
|
80
|
+
new.merge(Hash[ outputs.collect { |semantic, output| [output, semantic] } ])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|