trailblazer-operation 0.0.13 → 0.4.1
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 +5 -5
- data/.travis.yml +5 -3
- data/CHANGES.md +100 -0
- data/Gemfile +4 -2
- data/Rakefile +8 -6
- data/lib/trailblazer/operation.rb +80 -13
- data/lib/trailblazer/operation/callable.rb +42 -0
- data/lib/trailblazer/operation/class_dependencies.rb +25 -0
- data/lib/trailblazer/operation/deprecated_macro.rb +19 -0
- data/lib/trailblazer/operation/heritage.rb +30 -0
- data/lib/trailblazer/operation/inject.rb +36 -0
- data/lib/trailblazer/operation/inspect.rb +79 -0
- data/lib/trailblazer/operation/public_call.rb +55 -0
- data/lib/trailblazer/operation/railway.rb +32 -0
- data/lib/trailblazer/operation/railway/fast_track.rb +13 -0
- data/lib/trailblazer/operation/railway/macaroni.rb +23 -0
- data/lib/trailblazer/operation/railway/normalizer.rb +58 -0
- data/lib/trailblazer/operation/railway/task_builder.rb +37 -0
- data/lib/trailblazer/operation/result.rb +6 -4
- data/lib/trailblazer/operation/trace.rb +46 -0
- data/lib/trailblazer/operation/version.rb +1 -1
- data/test/call_test.rb +27 -8
- data/test/callable_test.rb +147 -0
- data/test/class_dependencies_test.rb +16 -0
- data/test/docs/doormat_test.rb +189 -0
- data/test/docs/macaroni_test.rb +33 -0
- data/test/docs/operation_test.rb +23 -0
- data/test/docs/wiring_test.rb +559 -0
- data/test/dry_container_test.rb +4 -0
- data/test/fast_track_test.rb +197 -0
- data/test/gemfiles/Gemfile.ruby-2.0 +1 -2
- data/test/gemfiles/Gemfile.ruby-2.0.lock +40 -0
- data/test/inheritance_test.rb +1 -1
- data/test/inspect_test.rb +43 -0
- data/test/introspect_test.rb +51 -0
- data/test/macro_test.rb +60 -0
- data/test/operation_test.rb +94 -0
- data/test/result_test.rb +14 -8
- data/test/ruby-2.0.0/operation_test.rb +61 -0
- data/test/ruby-2.0.0/step_test.rb +136 -0
- data/test/skill_test.rb +66 -48
- data/test/step_test.rb +228 -0
- data/test/task_wrap_test.rb +97 -0
- data/test/test_helper.rb +37 -0
- data/test/trace_test.rb +57 -0
- data/test/wire_test.rb +113 -0
- data/test/wiring/defaults_test.rb +197 -0
- data/test/wiring/subprocess_test.rb +70 -0
- data/trailblazer-operation.gemspec +3 -5
- metadata +68 -37
- data/lib/trailblazer/operation/1.9.3/option.rb +0 -36
- data/lib/trailblazer/operation/generic.rb +0 -12
- data/lib/trailblazer/operation/option.rb +0 -54
- data/lib/trailblazer/operation/pipetree.rb +0 -142
- data/lib/trailblazer/operation/skill.rb +0 -41
- data/lib/trailblazer/skill.rb +0 -70
- data/test/2.0.0-pipetree_test.rb +0 -100
- data/test/2.1.0-pipetree_test.rb +0 -100
- data/test/operation_skill_test.rb +0 -89
- data/test/pipetree_test.rb +0 -185
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d3347429bc2a448f6f41390b5d70aea2076d32235acb78f51563fbcb8f935f8e
|
4
|
+
data.tar.gz: 68200b340b34a5965cd773921b8282a4eb0f0ad56ae87e1b7ad2585a362cc02a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6824c50e6c8f48b587afc1e8a2f08b3b1813379c811f6b1017c6088bdd9836c445839a20cec3ac1407b33290ea5c4a1d3ee47da77854de8bfde7bf24a4230662
|
7
|
+
data.tar.gz: b0fb9530502238b3bfab54311c93793a4c4f028091ba72a7f9e71a3eb1f760edb077577d2e542d06d6650c392b160f464a44c6f1c7d90d79b9447e468f6935c3
|
data/.travis.yml
CHANGED
@@ -3,13 +3,15 @@ before_install:
|
|
3
3
|
- gem install bundler
|
4
4
|
matrix:
|
5
5
|
include:
|
6
|
-
- rvm: 1.9.3
|
7
|
-
gemfile: "test/gemfiles/Gemfile.ruby-1.9"
|
8
6
|
# - rvm: 2.0.0
|
9
7
|
# gemfile: "test/gemfiles/Gemfile.ruby-2.0"
|
10
8
|
- rvm: 2.1
|
11
9
|
gemfile: Gemfile
|
12
10
|
- rvm: 2.2.4
|
13
11
|
gemfile: Gemfile
|
14
|
-
- rvm: 2.3.
|
12
|
+
- rvm: 2.3.3
|
15
13
|
gemfile: Gemfile
|
14
|
+
- rvm: 2.4.0
|
15
|
+
gemfile: Gemfile
|
16
|
+
- rvm: jruby-9.1.13.0
|
17
|
+
env: JRUBY_OPTS="--profile.api"
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,103 @@
|
|
1
|
+
TODO:
|
2
|
+
* api to add your own task.
|
3
|
+
|
4
|
+
lots of work on the DSL specific parts.
|
5
|
+
Graph and Sequence to make it easier to wire anything.
|
6
|
+
macros can now add/modify the wiring, e.g. their end to the our end or the next task.
|
7
|
+
[ use circuit for actual step_args/initialize process, too? ]
|
8
|
+
You can now add an unlimited number of "your own" end events, which can then be interpreted on the outside (e.g. Endpoint)
|
9
|
+
* Introduced the `fast_track: true` option for steps. If you were returning `Railway.fail_fast!` and the like, you now need to declare that option, e.g.
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
step :my_validate!, fast_track: true
|
13
|
+
```
|
14
|
+
|
15
|
+
params:, rest: ..
|
16
|
+
|
17
|
+
|
18
|
+
## 0.4.1
|
19
|
+
|
20
|
+
* Use `activity-0.7.1`.
|
21
|
+
|
22
|
+
## 0.4.0
|
23
|
+
|
24
|
+
* Use `activity-0.7.0`.
|
25
|
+
|
26
|
+
## 0.3.1
|
27
|
+
|
28
|
+
* Moved `VariableMapping` to the `activity` gem.
|
29
|
+
|
30
|
+
## 0.3.0
|
31
|
+
|
32
|
+
* Use `activity` 0.6.0.
|
33
|
+
* Remove `Operation::__call__` in favor of one `call` that dispatches to either
|
34
|
+
* `call_with_public_interface` this implements the complicated public `Operation.()` semantic and will be faded out with the rise of workflow engines.
|
35
|
+
* `call_with_circuit_interface` is the circuit-compatible version that will be invoked on nested operations.
|
36
|
+
|
37
|
+
This might seem a bit "magical" but simplifies the interface a lot. In better languages, you could use method overloading for that, in Ruby, we have to
|
38
|
+
do that ourselves. This decision was made with the deprecation of `Operation.()` in mind. In the future, operations will mostly be invoked from
|
39
|
+
workflow engines and not directly, where the engine takes care of applying the correct interface.
|
40
|
+
|
41
|
+
## 0.2.5
|
42
|
+
|
43
|
+
* Minor fixes for activity 0.5.2.
|
44
|
+
|
45
|
+
## 0.2.4
|
46
|
+
|
47
|
+
* Use `Activity::FastTrack` signals.
|
48
|
+
|
49
|
+
## 0.2.2
|
50
|
+
|
51
|
+
* Use `activity-0.4.2`.
|
52
|
+
|
53
|
+
## 0.2.1
|
54
|
+
|
55
|
+
* Use `activity-0.4.1`.
|
56
|
+
|
57
|
+
## 0.2.0
|
58
|
+
|
59
|
+
* Cleanly separate `Activity` and `Operation` responsibilities. An operation is nothing more but a class around an activity, hosting instance methods and implementing inheritance.
|
60
|
+
|
61
|
+
## 0.1.4
|
62
|
+
|
63
|
+
* `TaskWrap.arguments_for_call` now returns the correct `circuit_options` where the `:runner` etc.'s already merged.
|
64
|
+
|
65
|
+
## 0.1.3
|
66
|
+
|
67
|
+
* New taskWrap API for `activity` 0.3.2.
|
68
|
+
|
69
|
+
## 0.1.2
|
70
|
+
|
71
|
+
* Add @mensfeld's "Macaroni" step style for a keyword-only signature for steps.
|
72
|
+
|
73
|
+
## 0.1.0
|
74
|
+
|
75
|
+
inspect: failure is << and success is >>
|
76
|
+
|
77
|
+
call vs __call__: it's now designed to be run in a composition where the skills stuff is done only once, and the reslt object is not necessary
|
78
|
+
|
79
|
+
FastTrack optional
|
80
|
+
Wrapped optional
|
81
|
+
|
82
|
+
* Add `pass` and `fail` as four-character aliases for `success` and `failure`.
|
83
|
+
* Remove `Uber::Callable` requirement and treat all non-`:symbol` steps as callable objects.
|
84
|
+
* Remove non-kw options for steps. All steps receive keyword args now:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
def model(options)
|
88
|
+
```
|
89
|
+
|
90
|
+
now must have a minimal signature as follows.
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
def model(options, **)
|
94
|
+
```
|
95
|
+
* Remove `Operation#[]` and `Operation#[]=`. Please only change state in `options`.
|
96
|
+
* API change for `step Macro()`: the macro's return value is now called with the low-level "Task API" signature `(direction, options, flow_options)`. You need to return `[direction, options, flow_options]`. There's a soft-deprecation warning.
|
97
|
+
* Remove support for Ruby 1.9.3 for now. This can be re-introduced on demand.
|
98
|
+
* Remove `pipetree` in favor of [`trailblazer-circuit`](https://github.com/trailblazer/trailblazer-circuit). This allows rich workflows and state machines in an operation.
|
99
|
+
* Remove `uber` dependency.
|
100
|
+
|
1
101
|
## 0.0.13
|
2
102
|
|
3
103
|
* Rename `Operation::New` to `:Instantiate` to avoid name clashes with `New` operations in applications.
|
data/Gemfile
CHANGED
@@ -9,5 +9,7 @@ gem "dry-auto_inject"
|
|
9
9
|
|
10
10
|
gem "minitest-line"
|
11
11
|
gem "benchmark-ips"
|
12
|
-
|
13
|
-
# gem "
|
12
|
+
|
13
|
+
# gem "trailblazer-developer", path: "../developer"
|
14
|
+
# gem "trailblazer-developer", git: "https://github.com/trailblazer/trailblazer-developer"
|
15
|
+
gem "trailblazer-activity", path: "../trailblazer-activity"
|
data/Rakefile
CHANGED
@@ -4,15 +4,17 @@ require "rake/testtask"
|
|
4
4
|
task :default => [:test]
|
5
5
|
|
6
6
|
Rake::TestTask.new(:test) do |test|
|
7
|
-
test.libs <<
|
7
|
+
test.libs << "test"
|
8
8
|
test.verbose = true
|
9
9
|
|
10
|
-
test_files = FileList[
|
10
|
+
test_files = FileList["test/**/*_test.rb"]
|
11
11
|
|
12
|
-
if
|
13
|
-
test_files = test_files - %w{test/dry_container_test.rb test/2.1.0-pipetree_test.rb
|
14
|
-
|
15
|
-
test_files = test_files - %w{test/
|
12
|
+
if RUBY_VERSION == "2.0.0"
|
13
|
+
# test_files = test_files - %w{test/dry_container_test.rb test/2.1.0-pipetree_test.rb}
|
14
|
+
test_files = test_files - %w{test/step_test.rb} + %w{test/ruby-2.0.0/step_test.rb}
|
15
|
+
test_files = test_files - %w{test/operation_test.rb} + %w{test/ruby-2.0.0/operation_test.rb}
|
16
|
+
else
|
17
|
+
test_files -= FileList["test/ruby-2.0.0/*"]
|
16
18
|
end
|
17
19
|
|
18
20
|
test.test_files = test_files
|
@@ -1,24 +1,91 @@
|
|
1
1
|
require "forwardable"
|
2
|
-
|
3
|
-
|
4
|
-
require "trailblazer/
|
5
|
-
require "trailblazer/
|
2
|
+
|
3
|
+
# trailblazer-context
|
4
|
+
require "trailblazer/option"
|
5
|
+
require "trailblazer/context"
|
6
|
+
require "trailblazer/container_chain"
|
7
|
+
|
8
|
+
require "trailblazer/activity"
|
9
|
+
require "trailblazer/activity/dsl/magnetic"
|
10
|
+
|
11
|
+
|
12
|
+
require "trailblazer/operation/callable"
|
13
|
+
|
14
|
+
require "trailblazer/operation/heritage"
|
15
|
+
require "trailblazer/operation/public_call" # TODO: Remove in 3.0.
|
16
|
+
require "trailblazer/operation/class_dependencies"
|
17
|
+
require "trailblazer/operation/deprecated_macro" # TODO: remove in 2.2.
|
18
|
+
require "trailblazer/operation/result"
|
19
|
+
require "trailblazer/operation/railway"
|
20
|
+
|
21
|
+
require "trailblazer/operation/railway/fast_track"
|
22
|
+
require "trailblazer/operation/railway/normalizer"
|
23
|
+
require "trailblazer/operation/trace"
|
24
|
+
|
25
|
+
require "trailblazer/operation/railway/macaroni"
|
6
26
|
|
7
27
|
module Trailblazer
|
8
28
|
# The Trailblazer-style operation.
|
9
29
|
# Note that you don't have to use our "opinionated" version with result object, skills, etc.
|
10
30
|
class Operation
|
11
|
-
extend Declarative::Heritage::Inherited
|
12
|
-
extend Declarative::Heritage::DSL
|
13
31
|
|
14
|
-
|
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
|
15
50
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
extend Skill::Call::Positional # ::call(params, options)
|
51
|
+
def self.initialize!
|
52
|
+
@activity = FastTrackActivity.clone
|
53
|
+
end
|
20
54
|
|
21
|
-
|
22
|
-
|
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
|
23
88
|
end
|
24
89
|
end
|
90
|
+
|
91
|
+
require "trailblazer/operation/inspect"
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Trailblazer
|
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::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::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::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,19 @@
|
|
1
|
+
# TODO: REMOVE IN 2.2.
|
2
|
+
module Trailblazer
|
3
|
+
module Operation::DeprecatedMacro
|
4
|
+
# Allows old macros with the `(input, options)` signature.
|
5
|
+
def self.call(proc, options)
|
6
|
+
warn %{[Trailblazer] 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,30 @@
|
|
1
|
+
module Trailblazer
|
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
|
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
|
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
|