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,11 @@
|
|
1
|
+
require "trailblazer/v2_1/operation"
|
2
|
+
|
3
|
+
require "trailblazer/v2_1/operation/inject"
|
4
|
+
|
5
|
+
require "trailblazer/v2_1/operation/model"
|
6
|
+
require "trailblazer/v2_1/operation/policy"
|
7
|
+
require "trailblazer/v2_1/operation/guard"
|
8
|
+
require "trailblazer/v2_1/operation/pundit"
|
9
|
+
require "trailblazer/v2_1/operation/nested"
|
10
|
+
require "trailblazer/v2_1/operation/rescue"
|
11
|
+
require "trailblazer/v2_1/operation/wrap"
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
# trailblazer-context
|
4
|
+
require "trailblazer/v2_1/option"
|
5
|
+
require "trailblazer/v2_1/context"
|
6
|
+
require "trailblazer/v2_1/container_chain"
|
7
|
+
|
8
|
+
require "trailblazer/v2_1/activity"
|
9
|
+
require "trailblazer/v2_1/activity/dsl/magnetic"
|
10
|
+
|
11
|
+
|
12
|
+
require "trailblazer/v2_1/operation/callable"
|
13
|
+
|
14
|
+
require "trailblazer/v2_1/operation/heritage"
|
15
|
+
require "trailblazer/v2_1/operation/public_call" # TODO: Remove in 3.0.
|
16
|
+
require "trailblazer/v2_1/operation/class_dependencies"
|
17
|
+
require "trailblazer/v2_1/operation/deprecated_macro" # TODO: remove in 2.2.
|
18
|
+
require "trailblazer/v2_1/operation/result"
|
19
|
+
require "trailblazer/v2_1/operation/railway"
|
20
|
+
|
21
|
+
require "trailblazer/v2_1/operation/railway/fast_track"
|
22
|
+
require "trailblazer/v2_1/operation/railway/normalizer"
|
23
|
+
require "trailblazer/v2_1/operation/trace"
|
24
|
+
|
25
|
+
require "trailblazer/v2_1/operation/railway/macaroni"
|
26
|
+
|
27
|
+
module Trailblazer::V2_1
|
28
|
+
# The Trailblazer::V2_1-style operation.
|
29
|
+
# Note that you don't have to use our "opinionated" version with result object, skills, etc.
|
30
|
+
class Operation
|
31
|
+
|
32
|
+
module FastTrackActivity
|
33
|
+
builder_options = {
|
34
|
+
track_end: Railway::End::Success.new(semantic: :success),
|
35
|
+
failure_end: Railway::End::Failure.new(semantic: :failure),
|
36
|
+
pass_fast_end: Railway::End::PassFast.new(semantic: :pass_fast),
|
37
|
+
fail_fast_end: Railway::End::FailFast.new(semantic: :fail_fast),
|
38
|
+
}
|
39
|
+
|
40
|
+
extend Activity::FastTrack( pipeline: Railway::Normalizer::Pipeline, builder_options: builder_options )
|
41
|
+
end
|
42
|
+
|
43
|
+
extend Skill::Accessors # ::[] and ::[]= # TODO: fade out this usage.
|
44
|
+
|
45
|
+
def self.inherited(subclass)
|
46
|
+
super
|
47
|
+
subclass.initialize!
|
48
|
+
heritage.(subclass)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.initialize!
|
52
|
+
@activity = FastTrackActivity.clone
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
extend Activity::Interface
|
57
|
+
|
58
|
+
module Process
|
59
|
+
def to_h
|
60
|
+
@activity.to_h.merge( activity: @activity )
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
extend Process # make ::call etc. class methods on Operation.
|
65
|
+
|
66
|
+
extend Heritage::Accessor
|
67
|
+
|
68
|
+
class << self
|
69
|
+
extend Forwardable # TODO: test those helpers
|
70
|
+
def_delegators :@activity, :Path, :Output, :End, :Track
|
71
|
+
def_delegators :@activity, :outputs
|
72
|
+
|
73
|
+
def step(task, options={}, &block); add_task!(:step, task, options, &block) end
|
74
|
+
def pass(task, options={}, &block); add_task!(:pass, task, options, &block) end
|
75
|
+
def fail(task, options={}, &block); add_task!(:fail, task, options, &block) end
|
76
|
+
|
77
|
+
alias_method :success, :pass
|
78
|
+
alias_method :failure, :fail
|
79
|
+
|
80
|
+
def add_task!(name, task, options, &block)
|
81
|
+
heritage.record(name, task, options, &block)
|
82
|
+
@activity.send(name, task, options, &block)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
extend PublicCall # ::call(params, { current_user: .. })
|
87
|
+
extend Trace # ::trace
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
require "trailblazer/v2_1/operation/inspect"
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "dry/auto_inject"
|
2
|
+
|
3
|
+
class Trailblazer::V2_1::Operation
|
4
|
+
# Thanks, @timriley! <3
|
5
|
+
# https://gist.github.com/timriley/d314a58da9784912159006e208ba8ea9
|
6
|
+
module AutoInject
|
7
|
+
class InjectStrategy < Module
|
8
|
+
ClassMethods = Class.new(Module)
|
9
|
+
|
10
|
+
attr_reader :container
|
11
|
+
attr_reader :dependency_map
|
12
|
+
attr_reader :class_mod
|
13
|
+
|
14
|
+
def initialize(container, *dependency_names)
|
15
|
+
@container = container
|
16
|
+
@dependency_map = Dry::AutoInject::DependencyMap.new(*dependency_names)
|
17
|
+
@class_mod = ClassMethods.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def included(klass)
|
21
|
+
define_call
|
22
|
+
|
23
|
+
klass.singleton_class.prepend @class_mod
|
24
|
+
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def define_call
|
31
|
+
class_mod.class_exec(container, dependency_map) do |container, dependency_map|
|
32
|
+
define_method :call_with_public_interface do |ctx={}, *dependencies|
|
33
|
+
ctx_with_deps = dependency_map.to_h.each_with_object({}) { |(name, identifier), obj|
|
34
|
+
obj[name] = ctx[name] || container[identifier]
|
35
|
+
}.merge(ctx)
|
36
|
+
|
37
|
+
super(ctx_with_deps, *dependencies)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.AutoInject(container)
|
45
|
+
Dry::AutoInject(container, strategies: {default: AutoInject::InjectStrategy})
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Trailblazer::V2_1
|
2
|
+
class Operation
|
3
|
+
# Use {Callable} if you have an operation or any other callable object that does
|
4
|
+
# _not_ expose an {Activity interface}. For example, {Operation.call} isn't compatible
|
5
|
+
# with activities, hence you need to decorate it using {Callable}. The returned object
|
6
|
+
# exposes an {Activity interface}.
|
7
|
+
#
|
8
|
+
# @param :call [Symbol] Method name to call
|
9
|
+
# @param options [Hash] Hash to merge into {circuit_options}, e.g. {:start_task}.
|
10
|
+
#
|
11
|
+
# @example Create and use a Callable instance.
|
12
|
+
# callable = Trailblazer::V2_1::Operation::Callable( Memo::Create, call: :__call__ )
|
13
|
+
# callable.( [ctx, {}] ) #=> Activity interface, ::call will invoke Memo::Create.__call__.
|
14
|
+
def self.Callable(*args)
|
15
|
+
Callable.new(*args)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Subprocess allows to have tasks with a different call interface and start event.
|
19
|
+
# @param activity any object with an {Activity interface}
|
20
|
+
class Callable
|
21
|
+
include Activity::Interface
|
22
|
+
|
23
|
+
def initialize(activity, call: :call, **options)
|
24
|
+
@activity = activity
|
25
|
+
@options = options
|
26
|
+
@call = call
|
27
|
+
end
|
28
|
+
|
29
|
+
def call(args, **circuit_options)
|
30
|
+
@activity.public_send(@call, args, circuit_options.merge(@options))
|
31
|
+
end
|
32
|
+
|
33
|
+
extend Forwardable
|
34
|
+
# @private
|
35
|
+
def_delegators :@activity, :to_h, :debug
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
%{#<Trailblazer::V2_1::Activity::Callable activity=#{@activity}>}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Dependencies can be defined on the operation. class level
|
2
|
+
class Trailblazer::V2_1::Operation
|
3
|
+
module Skill
|
4
|
+
# The class-level skill container: Operation::[], ::[]=.
|
5
|
+
module Accessors
|
6
|
+
# :private:
|
7
|
+
def skills
|
8
|
+
@skills ||= {}
|
9
|
+
end
|
10
|
+
|
11
|
+
extend Forwardable
|
12
|
+
def_delegators :skills, :[], :[]=
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# The use of this module is not encouraged and it is only here for backward-compatibility.
|
17
|
+
# Instead, please pass dependencies via containers, locals, or macros into the respective steps.
|
18
|
+
module ClassDependencies
|
19
|
+
def call_with_circuit_interface( (ctx, flow_options), **circuit_options )
|
20
|
+
@skills.each { |name, value| ctx[name] ||= value } # this resembles the behavior in 2.0. we didn't say we liked it.
|
21
|
+
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Trailblazer::V2_1
|
2
|
+
class Operation
|
3
|
+
module Contract
|
4
|
+
def self.Build(name: "default", constant: nil, builder: nil)
|
5
|
+
task = lambda do |(options, flow_options), **circuit_options|
|
6
|
+
result = Build.(options, circuit_options, name: name, constant: constant, builder: builder)
|
7
|
+
|
8
|
+
return Activity::TaskBuilder.binary_signal_for( result, Activity::Right, Activity::Left ),
|
9
|
+
[options, flow_options]
|
10
|
+
end
|
11
|
+
|
12
|
+
{ task: task, id: "contract.build" }
|
13
|
+
end
|
14
|
+
|
15
|
+
module Build
|
16
|
+
# Build contract at runtime.
|
17
|
+
def self.call(options, circuit_options, name: "default", constant: nil, builder: nil)
|
18
|
+
# TODO: we could probably clean this up a bit at some point.
|
19
|
+
contract_class = constant || options["contract.#{name}.class"] # DISCUSS: Injection possible here?
|
20
|
+
model = options[:model]
|
21
|
+
name = "contract.#{name}"
|
22
|
+
|
23
|
+
options[name] =
|
24
|
+
if builder
|
25
|
+
call_builder( options, circuit_options, builder: builder, constant: contract_class, name: name )
|
26
|
+
else
|
27
|
+
contract_class.new(model)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.call_builder(options, circuit_options, builder:raise, constant:raise, name:raise)
|
32
|
+
tmp_options = options.to_hash.merge(
|
33
|
+
constant: constant,
|
34
|
+
name: name
|
35
|
+
)
|
36
|
+
Trailblazer::V2_1::Option(builder).( options, tmp_options, circuit_options )
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module DSL
|
41
|
+
def self.extended(extender)
|
42
|
+
extender.extend(ClassDependencies)
|
43
|
+
warn "[Trailblazer::V2_1] Using `contract do...end` is deprecated. Please use a form class and the Builder( constant: <Form> ) option."
|
44
|
+
end
|
45
|
+
|
46
|
+
# This is the class level DSL method.
|
47
|
+
# Op.contract #=> returns contract class
|
48
|
+
# Op.contract do .. end # defines contract
|
49
|
+
# Op.contract CommentForm # copies (and subclasses) external contract.
|
50
|
+
# Op.contract CommentForm do .. end # copies and extends contract.
|
51
|
+
def contract(name=:default, constant=nil, base: Reform::Form, &block)
|
52
|
+
heritage.record(:contract, name, constant, &block)
|
53
|
+
|
54
|
+
path, form_class = Trailblazer::V2_1::DSL::Build.new.({ prefix: :contract, class: base, container: self }, name, constant, block)
|
55
|
+
|
56
|
+
self[path] = form_class
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# TODO: REMOVE IN 2.2.
|
2
|
+
module Trailblazer::V2_1
|
3
|
+
module Operation::DeprecatedMacro
|
4
|
+
# Allows old macros with the `(input, options)` signature.
|
5
|
+
def self.call(proc, options)
|
6
|
+
warn %{[Trailblazer::V2_1] Macros with API (input, options) are deprecated. Please use the "Task API" signature (options, flow_options) or use a simpler Callable. (#{proc})}
|
7
|
+
|
8
|
+
wrapped_proc = ->( (options, flow_options), **circuit_options ) do
|
9
|
+
result = proc.(circuit_options[:exec_context], options) # run the macro, with the deprecated signature.
|
10
|
+
|
11
|
+
direction = Activity::TaskBuilder.binary_signal_for(result, Activity::Right, Activity::Left)
|
12
|
+
|
13
|
+
return direction, [options, flow_options]
|
14
|
+
end
|
15
|
+
|
16
|
+
options.merge( task: wrapped_proc )
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Trailblazer::V2_1
|
2
|
+
class Operation
|
3
|
+
class DeprecatedOptions < Option
|
4
|
+
def self.call!(proc, direction, options, flow_options, *args)
|
5
|
+
if proc.is_a?(Proc) && proc.arity == 1
|
6
|
+
deprecate(proc)
|
7
|
+
proc.(options)
|
8
|
+
elsif proc.method(:call).arity == 1
|
9
|
+
deprecate(proc)
|
10
|
+
proc.(options)
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.deprecate(proc)
|
17
|
+
warn "[Trailblazer::V2_1] Please use the step API `def my_step!(options, **)` for your step: #{proc}"
|
18
|
+
end
|
19
|
+
end # DeprecatedOptions
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Trailblazer::V2_1::Operation
|
2
|
+
module Policy
|
3
|
+
def self.Guard(proc, name: :default, &block)
|
4
|
+
Policy.step( Guard.build(proc), name: name )
|
5
|
+
end
|
6
|
+
|
7
|
+
module Guard
|
8
|
+
def self.build(callable)
|
9
|
+
option = Trailblazer::V2_1::Option::KW(callable)
|
10
|
+
|
11
|
+
# this gets wrapped in a Operation::Result object.
|
12
|
+
->( (options, *), circuit_args ) do
|
13
|
+
Result.new(!!option.call(options, circuit_args), {})
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Trailblazer::V2_1
|
2
|
+
# This is copied from the Declarative gem. This might get removed in favor of a real heritage gem.
|
3
|
+
class Operation
|
4
|
+
class Heritage < Array
|
5
|
+
# Record inheritable assignments for replay in an inheriting class.
|
6
|
+
def record(method, *args, &block)
|
7
|
+
self << { method: method, args: args, block: block }
|
8
|
+
end
|
9
|
+
|
10
|
+
# Replay the recorded assignments on inheritor.
|
11
|
+
# Accepts a block that will allow processing the arguments for every recorded statement.
|
12
|
+
def call(inheritor, &block)
|
13
|
+
each { |cfg| call!(inheritor, cfg, &block) }
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def call!(inheritor, cfg)
|
18
|
+
yield cfg if block_given? # allow messing around with recorded arguments.
|
19
|
+
|
20
|
+
inheritor.send(cfg[:method], *cfg[:args], &cfg[:block])
|
21
|
+
end
|
22
|
+
|
23
|
+
module Accessor
|
24
|
+
def heritage
|
25
|
+
@heritage ||= Heritage.new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Trailblazer::V2_1
|
2
|
+
module Operation::Wrap
|
3
|
+
module Inject
|
4
|
+
# Returns an Alteration wirings that, when applied, inserts the {ReverseMergeDefaults} task
|
5
|
+
# before the {Wrap::Call} task. This is meant for macros and steps that accept a dependency
|
6
|
+
# injection but need a default parameter to be set if not injected.
|
7
|
+
# @returns ADDS
|
8
|
+
def self.Defaults(default_dependencies)
|
9
|
+
Module.new do
|
10
|
+
extend Activity::Path::Plan()
|
11
|
+
|
12
|
+
task ReverseMergeDefaults.new( default_dependencies ),
|
13
|
+
id: "ReverseMergeDefaults#{default_dependencies}",
|
14
|
+
before: "task_wrap.call_task"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
# @returns Task
|
20
|
+
# @param Hash list of key/value that should be set if not already assigned/set before (or injected from the outside).
|
21
|
+
class ReverseMergeDefaults
|
22
|
+
def initialize(defaults)
|
23
|
+
@defaults = defaults
|
24
|
+
end
|
25
|
+
|
26
|
+
def call((wrap_ctx, original_args), **circuit_options)
|
27
|
+
ctx = original_args[0][0]
|
28
|
+
|
29
|
+
@defaults.each { |k, v| ctx[k] ||= v }
|
30
|
+
|
31
|
+
return Activity::Right, [ wrap_ctx, original_args ]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end # Inject
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Trailblazer::V2_1
|
2
|
+
# Operation-specific circuit rendering. This is optimized for a linear railway circuit.
|
3
|
+
#
|
4
|
+
# @private
|
5
|
+
#
|
6
|
+
# NOTE: this is absolutely to be considered as prototyping and acts more like a test helper ATM as
|
7
|
+
# Inspect is not a mission-critical part.
|
8
|
+
class Operation
|
9
|
+
def self.introspect(*args)
|
10
|
+
Operation::Inspect.(*args)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Operation::Inspect
|
15
|
+
module_function
|
16
|
+
|
17
|
+
def call(operation, options={ style: :line })
|
18
|
+
# TODO: better introspection API.
|
19
|
+
|
20
|
+
alterations = Activity::Magnetic::Builder::Finalizer.adds_to_alterations(operation.to_h[:adds])
|
21
|
+
# DISCUSS: any other way to retrieve the Alterations?
|
22
|
+
|
23
|
+
# pp alterations
|
24
|
+
railway = alterations.instance_variable_get(:@groups).instance_variable_get(:@groups)[:main]
|
25
|
+
|
26
|
+
rows = railway.each_with_index.collect do |element, i|
|
27
|
+
magnetic_to, task, plus_poles = element.configuration
|
28
|
+
|
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
|
40
|
+
|
41
|
+
return inspect_line(rows) if options[:style] == :line
|
42
|
+
return inspect_rows(rows)
|
43
|
+
end
|
44
|
+
|
45
|
+
def inspect_func(step)
|
46
|
+
@inspect[step]
|
47
|
+
end
|
48
|
+
|
49
|
+
Operator = { :fail => "<<", :pass => ">>", :step => ">"}
|
50
|
+
|
51
|
+
def inspect_line(names)
|
52
|
+
string = names.collect { |i, (end_of_edge, name)| "#{Operator[end_of_edge]}#{name}" }.join(",")
|
53
|
+
"[#{string}]"
|
54
|
+
end
|
55
|
+
|
56
|
+
def inspect_rows(names)
|
57
|
+
string = names.collect do |i, (end_of_edge, name)|
|
58
|
+
operator = Operator[end_of_edge]
|
59
|
+
|
60
|
+
op = "#{operator}#{name}"
|
61
|
+
padding = 38
|
62
|
+
|
63
|
+
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
|
71
|
+
|
72
|
+
proc = proc.gsub(" ", "=")
|
73
|
+
|
74
|
+
sprintf("%2d %s", i, proc)
|
75
|
+
end.join("\n")
|
76
|
+
"\n#{string}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|