trailblazer-future 2.1.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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,101 @@
|
|
|
1
|
+
module Trailblazer::V2_1
|
|
2
|
+
module Activity::Magnetic
|
|
3
|
+
|
|
4
|
+
# TODO: move?
|
|
5
|
+
module Options
|
|
6
|
+
# Produce two hashes, one "local" options with DSL-specific options such as `:fast_track`,
|
|
7
|
+
# one with generic DSL options, for example tuples like `Right=>Output(:failure)`.
|
|
8
|
+
def self.normalize(options, local_keys)
|
|
9
|
+
local, foreign = {}, {}
|
|
10
|
+
options.each { |k,v| local_keys.include?(k) ? local[k] = v : foreign[k] = v }
|
|
11
|
+
|
|
12
|
+
return foreign, local
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Called from Path/Railway/FastTrack, creates the specific {Builder} instance.
|
|
17
|
+
def self.Builder(implementation, normalizer, builder_options={})
|
|
18
|
+
builder = implementation.new(normalizer, builder_options.freeze).freeze # e.g. Path.new(...)
|
|
19
|
+
|
|
20
|
+
return builder, implementation.InitialAdds(builder_options)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class Builder
|
|
24
|
+
def initialize(normalizer, builder_options)
|
|
25
|
+
@normalizer, @builder_options = normalizer, builder_options
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.merge(activity_adds, merged_adds)
|
|
29
|
+
merged_adds = merged_adds[2..-1] || []
|
|
30
|
+
|
|
31
|
+
activity_adds + merged_adds
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# DSL method to create a Path within an activity which is embedded.
|
|
35
|
+
#
|
|
36
|
+
# Output(:success) => Path() {}
|
|
37
|
+
def Path(*args)
|
|
38
|
+
Activity::DSL.Path(@normalizer, *args)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Public top-level entry point.
|
|
42
|
+
def insert(strategy, polarizer, task, options, &block)
|
|
43
|
+
normalizer = options[:normalizer] || @normalizer # DISCUSS: do this at a deeper point?
|
|
44
|
+
|
|
45
|
+
task, local_options, connection_options, sequence_options, extension_options = normalizer.(task, options)
|
|
46
|
+
|
|
47
|
+
polarizations = strategy.send(polarizer, @builder_options) # Railway.StepPolarizations( @builder_options )
|
|
48
|
+
|
|
49
|
+
insert_element( polarizations, task, local_options, connection_options, sequence_options, extension_options, &block )
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
# Internal top-level entry point to add task(s) and connections.
|
|
55
|
+
# High level interface for DSL calls like ::task or ::step.
|
|
56
|
+
def insert_element(polarizations, task, local_options, connection_options, sequence_options, extension_options, &block)
|
|
57
|
+
adds, *returned_options = Builder.adds_for(polarizations, task, local_options, connection_options, sequence_options, extension_options, &block)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @return Adds
|
|
61
|
+
def self.adds_for(polarizations, task, local_options, connection_options, sequence_options, extension_options, &block)
|
|
62
|
+
# go through all wiring options such as Output()=>:color.
|
|
63
|
+
polarizations_from_user_options, additional_adds = process_dsl_options(connection_options, local_options, &block)
|
|
64
|
+
|
|
65
|
+
polarizations = polarizations + polarizations_from_user_options
|
|
66
|
+
|
|
67
|
+
result = adds(task, polarizations, local_options, sequence_options, local_options)
|
|
68
|
+
|
|
69
|
+
return result + (local_options[:adds] || []) + additional_adds, task, local_options, connection_options, sequence_options, extension_options
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.process_dsl_options(options, id:nil, plus_poles:, **, &block)
|
|
73
|
+
DSL::ProcessOptions.(id, options, plus_poles, &block)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Low-level interface for DSL calls (e.g. Start, where "you know what you're doing")
|
|
77
|
+
# @private
|
|
78
|
+
def self.adds(task, polarizations, options, sequence_options, magnetic_to:nil, id:nil, plus_poles:, **) # DISCUSS: no :id ?
|
|
79
|
+
magnetic_to, plus_poles = PlusPoles.apply_polarizations(
|
|
80
|
+
polarizations,
|
|
81
|
+
magnetic_to,
|
|
82
|
+
plus_poles,
|
|
83
|
+
options
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
Add( id, task, magnetic_to, plus_poles,
|
|
87
|
+
options, #{ fast_track: true },
|
|
88
|
+
sequence_options #{ group: :main }
|
|
89
|
+
)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def self.Add(id, task, magnetic_to, plus_poles, options, sequence_options)
|
|
93
|
+
[
|
|
94
|
+
[ :add, [id, [ magnetic_to, task, plus_poles ], sequence_options] ],
|
|
95
|
+
]
|
|
96
|
+
end
|
|
97
|
+
end # Builder
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Trailblazer::V2_1
|
|
2
|
+
module Activity::Magnetic
|
|
3
|
+
# This normalizer only processes basic input and is meant for bootstrapping.
|
|
4
|
+
#
|
|
5
|
+
# task Callable, id: "success", before: "another"
|
|
6
|
+
class DefaultNormalizer
|
|
7
|
+
# Declarative::Variables
|
|
8
|
+
def self.build(plus_poles:, **options)
|
|
9
|
+
return new(plus_poles: plus_poles), options
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(**default_options)
|
|
13
|
+
@default_options = default_options
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Processes the user arguments from the DSL
|
|
17
|
+
def call(task, options)
|
|
18
|
+
local_options = @default_options.merge(options) # here, we merge default :plus_poles.
|
|
19
|
+
|
|
20
|
+
local_options, sequence_options = Options.normalize( local_options, Activity::Schema::Dependencies.sequence_keywords )
|
|
21
|
+
|
|
22
|
+
return task, local_options, {}, sequence_options, {}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# TODO: move me to Operation.
|
|
2
|
+
module Trailblazer::V2_1
|
|
3
|
+
module Activity::Magnetic
|
|
4
|
+
class Builder
|
|
5
|
+
|
|
6
|
+
class FastTrack < Builder
|
|
7
|
+
def self.for(normalizer, builder_options={}) # Build the Builder.
|
|
8
|
+
Activity::Magnetic::Builder(
|
|
9
|
+
FastTrack,
|
|
10
|
+
normalizer,
|
|
11
|
+
{ track_color: :success, end_semantic: :success, failure_color: :failure }.merge( builder_options )
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.StepPolarizations(**options)
|
|
16
|
+
[
|
|
17
|
+
*Railway.StepPolarizations(options),
|
|
18
|
+
StepPolarization.new(options)
|
|
19
|
+
]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.FailPolarizations(**options)
|
|
23
|
+
[
|
|
24
|
+
*Railway.FailPolarizations(options),
|
|
25
|
+
FailPolarization.new(options)
|
|
26
|
+
]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.PassPolarizations(**options)
|
|
30
|
+
[
|
|
31
|
+
*Railway.PassPolarizations(options),
|
|
32
|
+
PassPolarization.new(options)
|
|
33
|
+
]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# pass_fast: true simply means: color my :success Output with :pass_fast color
|
|
37
|
+
class StepPolarization < Railway::StepPolarization
|
|
38
|
+
def call(magnetic_to, plus_poles, options)
|
|
39
|
+
plus_poles = plus_poles.reconnect( :success => :pass_fast ) if options[:pass_fast]
|
|
40
|
+
plus_poles = plus_poles.reconnect( :failure => :fail_fast ) if options[:fail_fast]
|
|
41
|
+
|
|
42
|
+
# add fast track outputs if :fast_track
|
|
43
|
+
plus_poles = plus_poles.reverse_merge(
|
|
44
|
+
Activity.Output(Activity::FastTrack::FailFast, :fail_fast) => :fail_fast,
|
|
45
|
+
Activity.Output(Activity::FastTrack::PassFast, :pass_fast) => :pass_fast
|
|
46
|
+
) if options[:fast_track]
|
|
47
|
+
|
|
48
|
+
[
|
|
49
|
+
magnetic_to,
|
|
50
|
+
plus_poles
|
|
51
|
+
]
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class FailPolarization < Railway::StepPolarization
|
|
56
|
+
def call(magnetic_to, plus_poles, options)
|
|
57
|
+
plus_poles = plus_poles.reconnect( :failure => :fail_fast, :success => :fail_fast ) if options[:fail_fast]
|
|
58
|
+
plus_poles = plus_poles.reverse_merge( Activity.Output(Activity::FastTrack::FailFast, :fail_fast) => :fail_fast, Activity.Output(Activity::FastTrack::PassFast, :pass_fast) => :pass_fast ) if options[:fast_track]
|
|
59
|
+
|
|
60
|
+
[
|
|
61
|
+
magnetic_to,
|
|
62
|
+
plus_poles
|
|
63
|
+
]
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
class PassPolarization < Railway::StepPolarization
|
|
68
|
+
def call(magnetic_to, plus_poles, options)
|
|
69
|
+
plus_poles = plus_poles.reconnect( :success => :pass_fast, :failure => :pass_fast ) if options[:pass_fast]
|
|
70
|
+
plus_poles = plus_poles.reverse_merge( Activity.Output(Activity::FastTrack::FailFast, :fail_fast) => :fail_fast, Activity.Output(Activity::FastTrack::PassFast, :pass_fast) => :pass_fast ) if options[:fast_track]
|
|
71
|
+
|
|
72
|
+
[
|
|
73
|
+
magnetic_to,
|
|
74
|
+
plus_poles
|
|
75
|
+
]
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def self.default_plus_poles(*args)
|
|
80
|
+
Railway.default_plus_poles(*args)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Adds the End.fail_fast and End.pass_fast end to the Railway sequence.
|
|
84
|
+
def self.InitialAdds(pass_fast_end: Activity.End(:pass_fast), fail_fast_end: Activity.End(:fail_fast), **builder_options)
|
|
85
|
+
path_adds = Railway.InitialAdds(**builder_options)
|
|
86
|
+
|
|
87
|
+
ends =
|
|
88
|
+
adds(
|
|
89
|
+
pass_fast_end,
|
|
90
|
+
|
|
91
|
+
Path::EndEventPolarizations(builder_options),
|
|
92
|
+
|
|
93
|
+
{},
|
|
94
|
+
{ group: :end },
|
|
95
|
+
|
|
96
|
+
id: "End.pass_fast",
|
|
97
|
+
magnetic_to: [:pass_fast],
|
|
98
|
+
plus_poles: {},
|
|
99
|
+
)+
|
|
100
|
+
adds(
|
|
101
|
+
fail_fast_end,
|
|
102
|
+
|
|
103
|
+
Path::EndEventPolarizations(builder_options),
|
|
104
|
+
|
|
105
|
+
{},
|
|
106
|
+
{ group: :end },
|
|
107
|
+
|
|
108
|
+
magnetic_to: [:fail_fast],
|
|
109
|
+
id: "End.fail_fast",
|
|
110
|
+
plus_poles: {},
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
path_adds + ends
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
module Trailblazer::V2_1
|
|
2
|
+
module Activity::Magnetic
|
|
3
|
+
# One {Normalizer} instance is called for every DSL call (step/pass/fail etc.) and normalizes/defaults
|
|
4
|
+
# the user options, such as setting `:id`, connecting the task's outputs or wrapping the user's
|
|
5
|
+
# task via {TaskBuilder::Binary} in order to translate true/false to `Right` or `Left`.
|
|
6
|
+
#
|
|
7
|
+
# The Normalizer sits in the `@builder`, which receives all DSL calls from the Operation subclass.
|
|
8
|
+
class Normalizer
|
|
9
|
+
def self.build(task_builder: Activity::TaskBuilder.method(:Binary), default_outputs: Builder::Path.default_outputs, pipeline: Pipeline, extension:[], **options)
|
|
10
|
+
return new(
|
|
11
|
+
default_outputs: default_outputs,
|
|
12
|
+
extension: extension,
|
|
13
|
+
task_builder: task_builder,
|
|
14
|
+
pipeline: pipeline,
|
|
15
|
+
), options
|
|
16
|
+
end
|
|
17
|
+
|
|
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.
|
|
22
|
+
freeze
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def call(task, options)
|
|
26
|
+
ctx = {
|
|
27
|
+
task: task,
|
|
28
|
+
options: options,
|
|
29
|
+
task_builder: @task_builder,
|
|
30
|
+
default_outputs: @default_outputs,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
signal, (ctx, ) = @pipeline.( [ctx], {} )
|
|
34
|
+
|
|
35
|
+
return ctx[:options][:task], ctx[:local_options], ctx[:connection_options], ctx[:sequence_options], ctx[:extension_options]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# needs the basic Normalizer
|
|
39
|
+
|
|
40
|
+
# :default_plus_poles is an injectable option.
|
|
41
|
+
module Pipeline
|
|
42
|
+
extend Trailblazer::V2_1::Activity::Path( normalizer_class: DefaultNormalizer, plus_poles: PlusPoles.new.merge( Builder::Path.default_outputs.values ) ) # FIXME: the DefaultNormalizer actually doesn't need Left.
|
|
43
|
+
|
|
44
|
+
def self.split_options( ctx, task:, options:, ** )
|
|
45
|
+
keywords = extract_dsl_keywords(options)
|
|
46
|
+
extensions = extract_extensions(options)
|
|
47
|
+
|
|
48
|
+
# sort through the "original" user DSL options.
|
|
49
|
+
options, extension_options = Options.normalize( options, extensions ) # DISCUSS:
|
|
50
|
+
options, local_options = Options.normalize( options, keywords ) # DISCUSS:
|
|
51
|
+
local_options, sequence_options = Options.normalize( local_options, Activity::Schema::Dependencies.sequence_keywords )
|
|
52
|
+
|
|
53
|
+
ctx[:local_options],
|
|
54
|
+
ctx[:connection_options],
|
|
55
|
+
ctx[:sequence_options],
|
|
56
|
+
ctx[:extension_options] = local_options, options, sequence_options, extension_options
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Filter out connections, e.g. `Output(:fail_fast) => :success` and return only the keywords like `:id` or `:replace`.
|
|
60
|
+
def self.extract_dsl_keywords(options, connection_classes = [Activity::Output, Activity::DSL::OutputSemantic])
|
|
61
|
+
options.keys - options.keys.find_all { |k| connection_classes.include?( k.class ) }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.extract_extensions(options, extensions_classes = [Activity::DSL::Extension])
|
|
65
|
+
options.keys.find_all { |k| extensions_classes.include?( k.class ) }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# FIXME; why don't we use the extensions passed into the initializer?
|
|
69
|
+
def self.initialize_extension_option( ctx, options:, ** )
|
|
70
|
+
ctx[:options] = options.merge( Activity::DSL::Extension.new( Activity::DSL.method(:record) ) => true )
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Normalizes ctx[:options] (the user-options via the DSL) into the internal Hash format.
|
|
74
|
+
def self.normalize_for_macro( ctx, task:, options:, task_builder:, ** )
|
|
75
|
+
ctx[:options] =
|
|
76
|
+
if task.is_a?(::Hash) # macro.
|
|
77
|
+
task.merge(options) # Note that the user options are merged over the macro options.
|
|
78
|
+
else # user step
|
|
79
|
+
{ id: task }
|
|
80
|
+
.merge(options) # default :id
|
|
81
|
+
.merge( task: task_builder.(task) )
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# :outputs passed: I know what I want to have connected.
|
|
86
|
+
# no :outputs: use default_outputs
|
|
87
|
+
# ALWAYS connect all outputs to their semantic-color.
|
|
88
|
+
|
|
89
|
+
# Create the `plus_poles: <PlusPoles>` tuple where the PlusPoles instance will act as the interface
|
|
90
|
+
# to rewire or add connections for the DSL.
|
|
91
|
+
def self.initialize_plus_poles( ctx, local_options:, default_outputs:, ** )
|
|
92
|
+
outputs = local_options[:outputs] || default_outputs
|
|
93
|
+
|
|
94
|
+
ctx[:local_options] =
|
|
95
|
+
{
|
|
96
|
+
plus_poles: PlusPoles.initial(outputs),
|
|
97
|
+
}
|
|
98
|
+
.merge(local_options)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
task Activity::TaskBuilder::Binary( method(:initialize_extension_option) ), id: "initialize_extension_option"
|
|
102
|
+
task Activity::TaskBuilder::Binary( method(:normalize_for_macro) ), id: "normalize_for_macro"
|
|
103
|
+
|
|
104
|
+
task Activity::TaskBuilder::Binary( Activity::TaskWrap::VariableMapping.method(:normalizer_step_for_input_output) )
|
|
105
|
+
|
|
106
|
+
task Activity::TaskBuilder::Binary( method(:split_options) ), id: "split_options"
|
|
107
|
+
task Activity::TaskBuilder::Binary( method(:initialize_plus_poles) ), id: "initialize_plus_poles"
|
|
108
|
+
# task ->((ctx, _), **) { pp ctx; [Activity::Right, [ctx, _]] }
|
|
109
|
+
end
|
|
110
|
+
end # Normalizer
|
|
111
|
+
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
module Trailblazer::V2_1
|
|
2
|
+
module Activity::Magnetic
|
|
3
|
+
class Builder
|
|
4
|
+
|
|
5
|
+
class Path < Builder
|
|
6
|
+
# strategy_options:
|
|
7
|
+
# :track_color
|
|
8
|
+
# :end_semantic
|
|
9
|
+
def self.for(normalizer, builder_options={}) # Build the Builder.
|
|
10
|
+
Activity::Magnetic::Builder(
|
|
11
|
+
Path,
|
|
12
|
+
normalizer,
|
|
13
|
+
{ track_color: :success, end_semantic: :success }.merge( builder_options )
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# In most cases, a task has a binary signal, which is why we decided to make that
|
|
18
|
+
# the default output set.
|
|
19
|
+
def self.default_outputs
|
|
20
|
+
{
|
|
21
|
+
:success => Activity.Output(Activity::Right, :success),
|
|
22
|
+
:failure => Activity.Output(Activity::Left, :failure)
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @return [Adds] list of Adds instances that can be chained or added to an existing sequence.
|
|
27
|
+
def self.InitialAdds(**options)
|
|
28
|
+
StartAdds(**options) + EndAdds(**options)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# TODO: make this nicer.
|
|
32
|
+
def self.StartAdds(track_color:, end_semantic:, start_outputs: {success: self.default_outputs[:success]}, **)
|
|
33
|
+
builder_options={ track_color: track_color, end_semantic: end_semantic }
|
|
34
|
+
|
|
35
|
+
adds(
|
|
36
|
+
Activity::Start.new(semantic: :default),
|
|
37
|
+
|
|
38
|
+
TaskPolarizations(builder_options),
|
|
39
|
+
|
|
40
|
+
{}, { group: :start },
|
|
41
|
+
|
|
42
|
+
id: "Start.default",
|
|
43
|
+
magnetic_to: [],
|
|
44
|
+
plus_poles: PlusPoles.initial(start_outputs), # FIXME: this is actually redundant with Normalizer
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# TODO: make this nicer.
|
|
49
|
+
def self.EndAdds(track_color:, end_semantic:, track_end: Activity.End(end_semantic), end_id: nil, **)
|
|
50
|
+
# an end can either be a reference to another task,
|
|
51
|
+
# or a "real" end event.
|
|
52
|
+
if end_id
|
|
53
|
+
[[:magnetic_to,
|
|
54
|
+
[ end_id, [track_color] ] ]
|
|
55
|
+
]
|
|
56
|
+
else
|
|
57
|
+
builder_options={ track_color: track_color, end_semantic: end_semantic }
|
|
58
|
+
|
|
59
|
+
adds(
|
|
60
|
+
track_end,
|
|
61
|
+
|
|
62
|
+
EndEventPolarizations(builder_options), # only sets :magnetic_to.
|
|
63
|
+
|
|
64
|
+
{}, { group: :end },
|
|
65
|
+
|
|
66
|
+
id: "End.#{track_color}",
|
|
67
|
+
plus_poles: {},
|
|
68
|
+
magnetic_to: nil,
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def self.TaskPolarizations(track_color:, **)
|
|
74
|
+
[TaskPolarization.new( track_color: track_color )]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def self.EndEventPolarizations(track_color:, **)
|
|
78
|
+
[EndEventPolarization.new( track_color: track_color )]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
class TaskPolarization
|
|
82
|
+
def initialize(track_color:)
|
|
83
|
+
@track_color = track_color
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def call(magnetic_to, plus_poles, options)
|
|
87
|
+
[
|
|
88
|
+
magnetic_to || [@track_color],
|
|
89
|
+
plus_poles.reconnect( :success => @track_color )
|
|
90
|
+
]
|
|
91
|
+
end
|
|
92
|
+
end # TaskPolarization
|
|
93
|
+
|
|
94
|
+
class EndEventPolarization < TaskPolarization
|
|
95
|
+
def call(magnetic_to, plus_poles, options)
|
|
96
|
+
[
|
|
97
|
+
magnetic_to || [@track_color],
|
|
98
|
+
{}
|
|
99
|
+
]
|
|
100
|
+
end
|
|
101
|
+
end # EndEventPolarization
|
|
102
|
+
end # Path
|
|
103
|
+
end # Builder
|
|
104
|
+
end
|
|
105
|
+
end
|