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.
Files changed (161) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +6 -0
  4. data/CHANGES.md +4 -0
  5. data/LICENSE.txt +9 -0
  6. data/README.md +48 -0
  7. data/Rakefile +10 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/gems.rb +3 -0
  11. data/lib/trailblazer/future.rb +9 -0
  12. data/lib/trailblazer/future/version.rb +5 -0
  13. data/lib/trailblazer/v2_1/activity.rb +123 -0
  14. data/lib/trailblazer/v2_1/activity/config.rb +37 -0
  15. data/lib/trailblazer/v2_1/activity/dsl/add_task.rb +22 -0
  16. data/lib/trailblazer/v2_1/activity/dsl/helper.rb +68 -0
  17. data/lib/trailblazer/v2_1/activity/dsl/magnetic.rb +36 -0
  18. data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder.rb +101 -0
  19. data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder/default_normalizer.rb +26 -0
  20. data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder/fast_track.rb +118 -0
  21. data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder/normalizer.rb +113 -0
  22. data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder/path.rb +105 -0
  23. data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder/railway.rb +97 -0
  24. data/lib/trailblazer/v2_1/activity/dsl/magnetic/builder/state.rb +58 -0
  25. data/lib/trailblazer/v2_1/activity/dsl/magnetic/finalizer.rb +51 -0
  26. data/lib/trailblazer/v2_1/activity/dsl/magnetic/generate.rb +62 -0
  27. data/lib/trailblazer/v2_1/activity/dsl/magnetic/merge.rb +16 -0
  28. data/lib/trailblazer/v2_1/activity/dsl/magnetic/process_options.rb +76 -0
  29. data/lib/trailblazer/v2_1/activity/dsl/magnetic/structure/alterations.rb +44 -0
  30. data/lib/trailblazer/v2_1/activity/dsl/magnetic/structure/plus_poles.rb +85 -0
  31. data/lib/trailblazer/v2_1/activity/dsl/magnetic/structure/polarization.rb +23 -0
  32. data/lib/trailblazer/v2_1/activity/dsl/record.rb +11 -0
  33. data/lib/trailblazer/v2_1/activity/dsl/schema/dependencies.rb +46 -0
  34. data/lib/trailblazer/v2_1/activity/dsl/schema/sequence.rb +46 -0
  35. data/lib/trailblazer/v2_1/activity/dsl/strategy/build_state.rb +32 -0
  36. data/lib/trailblazer/v2_1/activity/dsl/strategy/fast_track.rb +24 -0
  37. data/lib/trailblazer/v2_1/activity/dsl/strategy/path.rb +26 -0
  38. data/lib/trailblazer/v2_1/activity/dsl/strategy/plan.rb +36 -0
  39. data/lib/trailblazer/v2_1/activity/dsl/strategy/railway.rb +23 -0
  40. data/lib/trailblazer/v2_1/activity/interface.rb +16 -0
  41. data/lib/trailblazer/v2_1/activity/introspect.rb +167 -0
  42. data/lib/trailblazer/v2_1/activity/present.rb +95 -0
  43. data/lib/trailblazer/v2_1/activity/structures.rb +57 -0
  44. data/lib/trailblazer/v2_1/activity/task_builder.rb +41 -0
  45. data/lib/trailblazer/v2_1/activity/task_wrap.rb +40 -0
  46. data/lib/trailblazer/v2_1/activity/task_wrap/call_task.rb +19 -0
  47. data/lib/trailblazer/v2_1/activity/task_wrap/merge.rb +23 -0
  48. data/lib/trailblazer/v2_1/activity/task_wrap/runner.rb +62 -0
  49. data/lib/trailblazer/v2_1/activity/task_wrap/trace.rb +44 -0
  50. data/lib/trailblazer/v2_1/activity/task_wrap/variable_mapping.rb +162 -0
  51. data/lib/trailblazer/v2_1/activity/testing.rb +32 -0
  52. data/lib/trailblazer/v2_1/activity/trace.rb +97 -0
  53. data/lib/trailblazer/v2_1/circuit.rb +71 -0
  54. data/lib/trailblazer/v2_1/container_chain.rb +45 -0
  55. data/lib/trailblazer/v2_1/context.rb +79 -0
  56. data/lib/trailblazer/v2_1/deprecation/call.rb +46 -0
  57. data/lib/trailblazer/v2_1/deprecation/context.rb +43 -0
  58. data/lib/trailblazer/v2_1/dsl.rb +47 -0
  59. data/lib/trailblazer/v2_1/macro.rb +11 -0
  60. data/lib/trailblazer/v2_1/macro/contract.rb +5 -0
  61. data/lib/trailblazer/v2_1/operation.rb +91 -0
  62. data/lib/trailblazer/v2_1/operation/auto_inject.rb +47 -0
  63. data/lib/trailblazer/v2_1/operation/callable.rb +42 -0
  64. data/lib/trailblazer/v2_1/operation/class_dependencies.rb +25 -0
  65. data/lib/trailblazer/v2_1/operation/contract.rb +61 -0
  66. data/lib/trailblazer/v2_1/operation/deprecated_macro.rb +19 -0
  67. data/lib/trailblazer/v2_1/operation/deprecations.rb +21 -0
  68. data/lib/trailblazer/v2_1/operation/guard.rb +18 -0
  69. data/lib/trailblazer/v2_1/operation/heritage.rb +30 -0
  70. data/lib/trailblazer/v2_1/operation/inject.rb +36 -0
  71. data/lib/trailblazer/v2_1/operation/inspect.rb +79 -0
  72. data/lib/trailblazer/v2_1/operation/model.rb +50 -0
  73. data/lib/trailblazer/v2_1/operation/module.rb +29 -0
  74. data/lib/trailblazer/v2_1/operation/nested.rb +98 -0
  75. data/lib/trailblazer/v2_1/operation/persist.rb +14 -0
  76. data/lib/trailblazer/v2_1/operation/policy.rb +44 -0
  77. data/lib/trailblazer/v2_1/operation/public_call.rb +55 -0
  78. data/lib/trailblazer/v2_1/operation/pundit.rb +38 -0
  79. data/lib/trailblazer/v2_1/operation/railway.rb +32 -0
  80. data/lib/trailblazer/v2_1/operation/railway/fast_track.rb +13 -0
  81. data/lib/trailblazer/v2_1/operation/railway/macaroni.rb +23 -0
  82. data/lib/trailblazer/v2_1/operation/railway/normalizer.rb +58 -0
  83. data/lib/trailblazer/v2_1/operation/railway/task_builder.rb +37 -0
  84. data/lib/trailblazer/v2_1/operation/rescue.rb +42 -0
  85. data/lib/trailblazer/v2_1/operation/responder.rb +18 -0
  86. data/lib/trailblazer/v2_1/operation/result.rb +30 -0
  87. data/lib/trailblazer/v2_1/operation/test.rb +17 -0
  88. data/lib/trailblazer/v2_1/operation/trace.rb +46 -0
  89. data/lib/trailblazer/v2_1/operation/validate.rb +76 -0
  90. data/lib/trailblazer/v2_1/operation/wrap.rb +83 -0
  91. data/lib/trailblazer/v2_1/option.rb +78 -0
  92. data/lib/trailblazer/v2_1/rails.rb +12 -0
  93. data/lib/trailblazer/v2_1/rails/cell.rb +22 -0
  94. data/lib/trailblazer/v2_1/rails/controller.rb +66 -0
  95. data/lib/trailblazer/v2_1/rails/form.rb +21 -0
  96. data/lib/trailblazer/v2_1/rails/railtie.rb +31 -0
  97. data/lib/trailblazer/v2_1/rails/railtie/extend_application_controller.rb +28 -0
  98. data/lib/trailblazer/v2_1/rails/railtie/loader.rb +58 -0
  99. data/lib/trailblazer/v2_1/rails/test/integration.rb +6 -0
  100. data/lib/trailblazer/v2_1/versions.txt +7 -0
  101. data/test/rails5.0/.gitignore +17 -0
  102. data/test/rails5.0/Gemfile +21 -0
  103. data/test/rails5.0/Rakefile +3 -0
  104. data/test/rails5.0/app/concepts/artist/cell/dashboard.rb +7 -0
  105. data/test/rails5.0/app/concepts/artist/cell/show.rb +4 -0
  106. data/test/rails5.0/app/concepts/artist/view/dashboard.erb +4 -0
  107. data/test/rails5.0/app/concepts/artist/view/show.erb +1 -0
  108. data/test/rails5.0/app/concepts/params/operation/with_args.rb +5 -0
  109. data/test/rails5.0/app/concepts/song/contract/form.rb +6 -0
  110. data/test/rails5.0/app/concepts/song/operation/create.rb +15 -0
  111. data/test/rails5.0/app/concepts/song/operation/show.rb +3 -0
  112. data/test/rails5.0/app/concepts/song/operation/update.rb +15 -0
  113. data/test/rails5.0/app/controllers/application_controller.rb +46 -0
  114. data/test/rails5.0/app/controllers/args_controller.rb +5 -0
  115. data/test/rails5.0/app/controllers/artists_controller.rb +24 -0
  116. data/test/rails5.0/app/controllers/params_controller.rb +11 -0
  117. data/test/rails5.0/app/controllers/songs_controller.rb +35 -0
  118. data/test/rails5.0/app/models/artist.rb +2 -0
  119. data/test/rails5.0/app/models/song.rb +2 -0
  120. data/test/rails5.0/app/views/args/with_args.html.erb +1 -0
  121. data/test/rails5.0/app/views/layouts/application.html.erb +2 -0
  122. data/test/rails5.0/app/views/songs/edit.html.erb +4 -0
  123. data/test/rails5.0/app/views/songs/new.html.erb +5 -0
  124. data/test/rails5.0/app/views/songs/new_with_result.html.erb +3 -0
  125. data/test/rails5.0/app/views/songs/show.html.erb +3 -0
  126. data/test/rails5.0/bin/bundle +3 -0
  127. data/test/rails5.0/bin/rails +4 -0
  128. data/test/rails5.0/bin/rake +4 -0
  129. data/test/rails5.0/bin/setup +29 -0
  130. data/test/rails5.0/config.ru +4 -0
  131. data/test/rails5.0/config/application.rb +25 -0
  132. data/test/rails5.0/config/boot.rb +3 -0
  133. data/test/rails5.0/config/database.yml +21 -0
  134. data/test/rails5.0/config/environment.rb +5 -0
  135. data/test/rails5.0/config/environments/development.rb +41 -0
  136. data/test/rails5.0/config/environments/test.rb +42 -0
  137. data/test/rails5.0/config/initializers/assets.rb +11 -0
  138. data/test/rails5.0/config/initializers/backtrace_silencers.rb +7 -0
  139. data/test/rails5.0/config/initializers/cookies_serializer.rb +3 -0
  140. data/test/rails5.0/config/initializers/filter_parameter_logging.rb +4 -0
  141. data/test/rails5.0/config/initializers/inflections.rb +16 -0
  142. data/test/rails5.0/config/initializers/mime_types.rb +4 -0
  143. data/test/rails5.0/config/initializers/session_store.rb +3 -0
  144. data/test/rails5.0/config/initializers/wrap_parameters.rb +14 -0
  145. data/test/rails5.0/config/locales/en.yml +23 -0
  146. data/test/rails5.0/config/routes.rb +15 -0
  147. data/test/rails5.0/config/secrets.yml +17 -0
  148. data/test/rails5.0/db/migrate/20161122145124_create_songs.rb +8 -0
  149. data/test/rails5.0/db/schema.rb +19 -0
  150. data/test/rails5.0/log/.keep +0 -0
  151. data/test/rails5.0/test/concepts/song/operation/create_test.rb +11 -0
  152. data/test/rails5.0/test/concepts/song/operation/update_test.rb +34 -0
  153. data/test/rails5.0/test/integration/.keep +0 -0
  154. data/test/rails5.0/test/integration/args_controller_test.rb +8 -0
  155. data/test/rails5.0/test/integration/artists_controller_test.rb +28 -0
  156. data/test/rails5.0/test/integration/params_controller_test.rb +8 -0
  157. data/test/rails5.0/test/integration/songs_controller_test.rb +40 -0
  158. data/test/rails5.0/test/test_helper.rb +7 -0
  159. data/test/test_helper.rb +5 -0
  160. data/trailblazer-future.gemspec +25 -0
  161. 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,5 @@
1
+ require "reform"
2
+ require "trailblazer/v2_1/operation"
3
+ require "trailblazer/v2_1/operation/contract"
4
+ require "trailblazer/v2_1/operation/validate"
5
+ require "trailblazer/v2_1/operation/persist"
@@ -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