trailblazer-future 2.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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