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