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,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
|