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
@@ -0,0 +1,70 @@
|
|
1
|
+
# require "test_helper"
|
2
|
+
|
3
|
+
# class WiringWithNestedTest < Minitest::Spec
|
4
|
+
# MyEnd = Class.new(Trailblazer::Circuit::End)
|
5
|
+
|
6
|
+
# class Create < Trailblazer::Operation
|
7
|
+
# class Edit < Trailblazer::Operation
|
8
|
+
# step :a
|
9
|
+
|
10
|
+
# def a(options, a_return:, **)
|
11
|
+
# options["a"] = 1
|
12
|
+
# a_return
|
13
|
+
# end
|
14
|
+
|
15
|
+
# # operations should expose their outputs with proper naming.
|
16
|
+
# #
|
17
|
+
# # {#<Trailblazer::Operation::Railway::End::Success:0x00000001b22310
|
18
|
+
# # @name=:success,
|
19
|
+
# # @options={}>=>{:role=>:success},
|
20
|
+
# # #<Trailblazer::Operation::Railway::End::Failure:0x00000001b222c0
|
21
|
+
# # @name=:failure,
|
22
|
+
# # @options={}>=>{:role=>:unauthorized}}
|
23
|
+
# def self.outputs
|
24
|
+
# # Outputs::Only(super, :success, :failure)
|
25
|
+
# # Outputs::Update( outputs, failure: { role: :unauthorized} )
|
26
|
+
|
27
|
+
# outs = super.to_a
|
28
|
+
|
29
|
+
# outs = Hash[*(outs[0]+outs[1])]
|
30
|
+
|
31
|
+
# outs.merge( outs.keys[1] => { role: :unauthorized } )
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
|
35
|
+
# attach MyEnd.new(:myend), id: "End.unauthorized"
|
36
|
+
|
37
|
+
# step ( { task: Trailblazer::Activity::Subprocess( Edit, call: :__call__ ),
|
38
|
+
# node_data: { id: "Nested/" },
|
39
|
+
# outputs: Edit.outputs, # THIS SHOULD OVERRIDE.
|
40
|
+
# connect_to: Merge({ unauthorized: "End.unauthorized" }) # connects :success automatically.
|
41
|
+
# }), fast_track: true
|
42
|
+
|
43
|
+
# step :b
|
44
|
+
# fail :f
|
45
|
+
|
46
|
+
# def b(options, a:, **)
|
47
|
+
# options["b"] = a+1
|
48
|
+
# end
|
49
|
+
|
50
|
+
# def f(options, a:, **)
|
51
|
+
# options["f"] = a+2
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
|
55
|
+
# # Edit ==> true, will run :b
|
56
|
+
# it do
|
57
|
+
# result = Create.({}, a_return: true )
|
58
|
+
# result.inspect("a", "b", "f").must_equal %{<Result:true [1, 2, nil] >}
|
59
|
+
# result.event.must_be_instance_of Trailblazer::Operation::Railway::End::Success
|
60
|
+
# end
|
61
|
+
|
62
|
+
# # Edit ==> false, will end on End.unauthorized.
|
63
|
+
# it do
|
64
|
+
# result = Create.({}, a_return: false )
|
65
|
+
# result.inspect("a", "b", "f").must_equal %{<Result:false [1, nil, nil] >}
|
66
|
+
# result.event.must_be_instance_of MyEnd
|
67
|
+
|
68
|
+
# # Create.trace({}, a_return: false ).wtf
|
69
|
+
# end
|
70
|
+
# end
|
@@ -17,14 +17,12 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
|
21
|
-
spec.add_dependency "
|
22
|
-
spec.add_dependency "declarative"
|
23
|
-
spec.add_dependency "pipetree", ">= 0.1.1", "< 0.2.0"
|
20
|
+
spec.add_dependency "trailblazer-activity", ">= 0.7.1", "< 0.8.0"
|
21
|
+
spec.add_dependency "trailblazer-context", ">= 0.1.1", "< 0.3.0"
|
24
22
|
|
25
23
|
spec.add_development_dependency "bundler"
|
26
24
|
spec.add_development_dependency "rake"
|
27
25
|
spec.add_development_dependency "minitest"
|
28
26
|
|
29
|
-
spec.required_ruby_version = '>=
|
27
|
+
spec.required_ruby_version = '>= 2.0.0'
|
30
28
|
end
|
metadata
CHANGED
@@ -1,45 +1,37 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trailblazer-operation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: trailblazer-activity
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
-
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: declarative
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
19
|
+
version: 0.7.1
|
20
|
+
- - "<"
|
32
21
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
22
|
+
version: 0.8.0
|
34
23
|
type: :runtime
|
35
24
|
prerelease: false
|
36
25
|
version_requirements: !ruby/object:Gem::Requirement
|
37
26
|
requirements:
|
38
27
|
- - ">="
|
39
28
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
29
|
+
version: 0.7.1
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.8.0
|
41
33
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
34
|
+
name: trailblazer-context
|
43
35
|
requirement: !ruby/object:Gem::Requirement
|
44
36
|
requirements:
|
45
37
|
- - ">="
|
@@ -47,7 +39,7 @@ dependencies:
|
|
47
39
|
version: 0.1.1
|
48
40
|
- - "<"
|
49
41
|
- !ruby/object:Gem::Version
|
50
|
-
version: 0.
|
42
|
+
version: 0.3.0
|
51
43
|
type: :runtime
|
52
44
|
prerelease: false
|
53
45
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -57,7 +49,7 @@ dependencies:
|
|
57
49
|
version: 0.1.1
|
58
50
|
- - "<"
|
59
51
|
- !ruby/object:Gem::Version
|
60
|
-
version: 0.
|
52
|
+
version: 0.3.0
|
61
53
|
- !ruby/object:Gem::Dependency
|
62
54
|
name: bundler
|
63
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,28 +106,51 @@ files:
|
|
114
106
|
- README.md
|
115
107
|
- Rakefile
|
116
108
|
- lib/trailblazer/operation.rb
|
117
|
-
- lib/trailblazer/operation/
|
118
|
-
- lib/trailblazer/operation/
|
119
|
-
- lib/trailblazer/operation/
|
120
|
-
- lib/trailblazer/operation/
|
109
|
+
- lib/trailblazer/operation/callable.rb
|
110
|
+
- lib/trailblazer/operation/class_dependencies.rb
|
111
|
+
- lib/trailblazer/operation/deprecated_macro.rb
|
112
|
+
- lib/trailblazer/operation/heritage.rb
|
113
|
+
- lib/trailblazer/operation/inject.rb
|
114
|
+
- lib/trailblazer/operation/inspect.rb
|
115
|
+
- lib/trailblazer/operation/public_call.rb
|
116
|
+
- lib/trailblazer/operation/railway.rb
|
117
|
+
- lib/trailblazer/operation/railway/fast_track.rb
|
118
|
+
- lib/trailblazer/operation/railway/macaroni.rb
|
119
|
+
- lib/trailblazer/operation/railway/normalizer.rb
|
120
|
+
- lib/trailblazer/operation/railway/task_builder.rb
|
121
121
|
- lib/trailblazer/operation/result.rb
|
122
|
-
- lib/trailblazer/operation/
|
122
|
+
- lib/trailblazer/operation/trace.rb
|
123
123
|
- lib/trailblazer/operation/version.rb
|
124
|
-
- lib/trailblazer/skill.rb
|
125
|
-
- test/2.0.0-pipetree_test.rb
|
126
|
-
- test/2.1.0-pipetree_test.rb
|
127
124
|
- test/benchmark/skill_resolver_benchmark.rb
|
128
125
|
- test/call_test.rb
|
126
|
+
- test/callable_test.rb
|
127
|
+
- test/class_dependencies_test.rb
|
128
|
+
- test/docs/doormat_test.rb
|
129
|
+
- test/docs/macaroni_test.rb
|
130
|
+
- test/docs/operation_test.rb
|
131
|
+
- test/docs/wiring_test.rb
|
129
132
|
- test/dry_container_test.rb
|
133
|
+
- test/fast_track_test.rb
|
130
134
|
- test/gemfiles/Gemfile.ruby-1.9
|
131
135
|
- test/gemfiles/Gemfile.ruby-2.0
|
136
|
+
- test/gemfiles/Gemfile.ruby-2.0.lock
|
132
137
|
- test/gemfiles/Gemfile.ruby-2.3
|
133
138
|
- test/inheritance_test.rb
|
134
|
-
- test/
|
135
|
-
- test/
|
139
|
+
- test/inspect_test.rb
|
140
|
+
- test/introspect_test.rb
|
141
|
+
- test/macro_test.rb
|
142
|
+
- test/operation_test.rb
|
136
143
|
- test/result_test.rb
|
144
|
+
- test/ruby-2.0.0/operation_test.rb
|
145
|
+
- test/ruby-2.0.0/step_test.rb
|
137
146
|
- test/skill_test.rb
|
147
|
+
- test/step_test.rb
|
148
|
+
- test/task_wrap_test.rb
|
138
149
|
- test/test_helper.rb
|
150
|
+
- test/trace_test.rb
|
151
|
+
- test/wire_test.rb
|
152
|
+
- test/wiring/defaults_test.rb
|
153
|
+
- test/wiring/subprocess_test.rb
|
139
154
|
- trailblazer-operation.gemspec
|
140
155
|
homepage: http://trailblazer.to
|
141
156
|
licenses:
|
@@ -149,7 +164,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
149
164
|
requirements:
|
150
165
|
- - ">="
|
151
166
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
167
|
+
version: 2.0.0
|
153
168
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
169
|
requirements:
|
155
170
|
- - ">="
|
@@ -157,22 +172,38 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
172
|
version: '0'
|
158
173
|
requirements: []
|
159
174
|
rubyforge_project:
|
160
|
-
rubygems_version: 2.
|
175
|
+
rubygems_version: 2.7.3
|
161
176
|
signing_key:
|
162
177
|
specification_version: 4
|
163
178
|
summary: Trailblazer's operation object with railway flow and integrated error handling.
|
164
179
|
test_files:
|
165
|
-
- test/2.0.0-pipetree_test.rb
|
166
|
-
- test/2.1.0-pipetree_test.rb
|
167
180
|
- test/benchmark/skill_resolver_benchmark.rb
|
168
181
|
- test/call_test.rb
|
182
|
+
- test/callable_test.rb
|
183
|
+
- test/class_dependencies_test.rb
|
184
|
+
- test/docs/doormat_test.rb
|
185
|
+
- test/docs/macaroni_test.rb
|
186
|
+
- test/docs/operation_test.rb
|
187
|
+
- test/docs/wiring_test.rb
|
169
188
|
- test/dry_container_test.rb
|
189
|
+
- test/fast_track_test.rb
|
170
190
|
- test/gemfiles/Gemfile.ruby-1.9
|
171
191
|
- test/gemfiles/Gemfile.ruby-2.0
|
192
|
+
- test/gemfiles/Gemfile.ruby-2.0.lock
|
172
193
|
- test/gemfiles/Gemfile.ruby-2.3
|
173
194
|
- test/inheritance_test.rb
|
174
|
-
- test/
|
175
|
-
- test/
|
195
|
+
- test/inspect_test.rb
|
196
|
+
- test/introspect_test.rb
|
197
|
+
- test/macro_test.rb
|
198
|
+
- test/operation_test.rb
|
176
199
|
- test/result_test.rb
|
200
|
+
- test/ruby-2.0.0/operation_test.rb
|
201
|
+
- test/ruby-2.0.0/step_test.rb
|
177
202
|
- test/skill_test.rb
|
203
|
+
- test/step_test.rb
|
204
|
+
- test/task_wrap_test.rb
|
178
205
|
- test/test_helper.rb
|
206
|
+
- test/trace_test.rb
|
207
|
+
- test/wire_test.rb
|
208
|
+
- test/wiring/defaults_test.rb
|
209
|
+
- test/wiring/subprocess_test.rb
|
@@ -1,36 +0,0 @@
|
|
1
|
-
class Trailblazer::Operation
|
2
|
-
# :private:
|
3
|
-
module Option
|
4
|
-
def self.call(proc, &block)
|
5
|
-
type = :proc
|
6
|
-
|
7
|
-
option =
|
8
|
-
if proc.is_a? Symbol
|
9
|
-
type = :symbol
|
10
|
-
->(input, _options) { call_method(proc, input, _options) }
|
11
|
-
elsif proc.is_a? Proc
|
12
|
-
->(input, _options) { call_proc(proc, input, _options) }
|
13
|
-
elsif proc.is_a? Uber::Callable
|
14
|
-
type = :callable
|
15
|
-
->(input, _options) { call_callable(proc, input, _options) }
|
16
|
-
end
|
17
|
-
|
18
|
-
yield type if block_given?
|
19
|
-
option
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.call_proc(proc, input, options)
|
23
|
-
proc.(options)
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.call_method(proc, input, options)
|
27
|
-
input.send(proc, options)
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.call_callable(callable, input, options)
|
31
|
-
callable.(options)
|
32
|
-
end
|
33
|
-
|
34
|
-
KW = Option
|
35
|
-
end # Option
|
36
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
class Trailblazer::Operation
|
2
|
-
# :private:
|
3
|
-
# This code is not beautiful, but could also be worse.
|
4
|
-
# I'm expecting some of this to go to Uber, as we use this pattern everywhere.
|
5
|
-
class Option
|
6
|
-
def self.call(proc, &block)
|
7
|
-
type = :proc
|
8
|
-
|
9
|
-
option =
|
10
|
-
if proc.is_a? Symbol
|
11
|
-
type = :symbol
|
12
|
-
->(input, *_options) { call_method(proc, input, *_options) }
|
13
|
-
elsif proc.is_a? Proc
|
14
|
-
->(input, *_options) { call_proc(proc, input, *_options) }
|
15
|
-
elsif proc.is_a? Uber::Callable
|
16
|
-
type = :callable
|
17
|
-
->(input, *_options) { call_callable(proc, input, *_options) }
|
18
|
-
end
|
19
|
-
|
20
|
-
yield type if block_given?
|
21
|
-
option
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.call_proc(proc, input, *options)
|
25
|
-
proc.(*options)
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.call_method(proc, input, *options)
|
29
|
-
input.send(proc, *options)
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.call_callable(callable, input, *options)
|
33
|
-
callable.(*options)
|
34
|
-
end
|
35
|
-
|
36
|
-
# Call the option with keyword arguments. Ruby <= 2.0.
|
37
|
-
class KW < Option
|
38
|
-
def self.call_proc(proc, input, options, tmp_options={})
|
39
|
-
return proc.(options) if proc.arity == 1
|
40
|
-
proc.(options, **options.to_hash(tmp_options))
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.call_method(proc, input, options, tmp_options={})
|
44
|
-
return input.send(proc, options) if input.method(proc).arity == 1 # TODO: remove this
|
45
|
-
input.send(proc, options, **options.to_hash(tmp_options))
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.call_callable(callable, input, options, tmp_options={})
|
49
|
-
return callable.(options) if callable.method(:call).arity == 1
|
50
|
-
callable.(options, **options.to_hash(tmp_options))
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,142 +0,0 @@
|
|
1
|
-
require "pipetree"
|
2
|
-
require "pipetree/railway"
|
3
|
-
require "trailblazer/operation/result"
|
4
|
-
|
5
|
-
if RUBY_VERSION == "1.9.3"
|
6
|
-
require "trailblazer/operation/1.9.3/option" # TODO: rename to something better.
|
7
|
-
else
|
8
|
-
require "trailblazer/operation/option" # TODO: rename to something better.
|
9
|
-
end
|
10
|
-
|
11
|
-
class Trailblazer::Operation
|
12
|
-
Instantiate = ->(klass, options) { klass.new(options) } # returns operation instance.
|
13
|
-
|
14
|
-
# Implements the API to populate the operation's pipetree and
|
15
|
-
# `Operation::call` to invoke the latter.
|
16
|
-
# Learn more about the Pipetree gem here: https://github.com/apotonick/pipetree
|
17
|
-
module Pipetree
|
18
|
-
def self.included(includer)
|
19
|
-
includer.extend ClassMethods # ::call, ::inititalize_pipetree!
|
20
|
-
includer.extend DSL # ::|, ::> and friends.
|
21
|
-
|
22
|
-
includer.initialize_pipetree!
|
23
|
-
end
|
24
|
-
|
25
|
-
module ClassMethods
|
26
|
-
# Top-level, this method is called when you do Create.() and where
|
27
|
-
# all the fun starts, ends, and hopefully starts again.
|
28
|
-
def call(options)
|
29
|
-
pipe = self["pipetree"] # TODO: injectable? WTF? how cool is that?
|
30
|
-
|
31
|
-
last, operation = pipe.(self, options)
|
32
|
-
|
33
|
-
# Any subclass of Right will be interpreted as successful.
|
34
|
-
Result.new(!!(last <= Railway::Right), options)
|
35
|
-
end
|
36
|
-
|
37
|
-
# This method would be redundant if Ruby had a Class::finalize! method the way
|
38
|
-
# Dry.RB provides it. It has to be executed with every subclassing.
|
39
|
-
def initialize_pipetree!
|
40
|
-
heritage.record :initialize_pipetree!
|
41
|
-
|
42
|
-
self["pipetree"] = Railway.new
|
43
|
-
|
44
|
-
strut = ->(last, input, options) { [last, Instantiate.(input, options)] } # first step in pipe.
|
45
|
-
self["pipetree"].add(Railway::Right, strut, name: "operation.new") # DISCUSS: using pipe API directly here. clever?
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
class Railway < ::Pipetree::Railway
|
50
|
-
FailFast = Class.new(Left)
|
51
|
-
PassFast = Class.new(Right)
|
52
|
-
|
53
|
-
def self.fail! ; Left end
|
54
|
-
def self.fail_fast!; FailFast end
|
55
|
-
def self.pass! ; Right end
|
56
|
-
def self.pass_fast!; PassFast end
|
57
|
-
end
|
58
|
-
|
59
|
-
# The Strut wrapping each step. Makes sure that Track signals are returned immediately.
|
60
|
-
class Switch < ::Pipetree::Railway::Strut
|
61
|
-
Decider = ->(result, config, *args) do
|
62
|
-
return result if result.is_a?(Class) && result <= Railway::Track # this might be pretty slow?
|
63
|
-
|
64
|
-
config[:decider_class].(result, config, *args) # e.g. And::Decider.(result, ..)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Strut that doesn't evaluate the step's result but stays on `last` or configured :signal.
|
69
|
-
class Stay < ::Pipetree::Railway::Strut
|
70
|
-
Decider = ->(result, config, last, *) { config[:signal] || last }
|
71
|
-
end
|
72
|
-
|
73
|
-
module DSL
|
74
|
-
def success(*args); add(Railway::Right, Stay::Decider, *args) end
|
75
|
-
def failure(*args); add(Railway::Left, Stay::Decider, *args) end
|
76
|
-
def step(*args) ; add(Railway::Right, Railway::And::Decider, *args) end
|
77
|
-
|
78
|
-
private
|
79
|
-
# Operation-level entry point.
|
80
|
-
def add(track, decider_class, proc, options={})
|
81
|
-
heritage.record(:add, track, decider_class, proc, options)
|
82
|
-
|
83
|
-
DSL.insert(self["pipetree"], track, decider_class, proc, options)
|
84
|
-
end
|
85
|
-
|
86
|
-
def self.insert(pipe, track, decider_class, proc, options={}) # TODO: make :name required arg.
|
87
|
-
_proc, options = proc.is_a?(Array) ? macro!(proc, options) : step!(proc, options)
|
88
|
-
|
89
|
-
options = options.merge(replace: options[:name]) if options[:override] # :override
|
90
|
-
strut_class, strut_options = AddOptions.(decider_class, options) # :fail_fast and friends.
|
91
|
-
|
92
|
-
pipe.add(track, strut_class.new(_proc, strut_options), options)
|
93
|
-
end
|
94
|
-
|
95
|
-
def self.macro!(proc, options)
|
96
|
-
_proc, macro_options = proc
|
97
|
-
|
98
|
-
[ _proc, macro_options.merge(options) ]
|
99
|
-
end
|
100
|
-
|
101
|
-
def self.step!(proc, options)
|
102
|
-
name = ""
|
103
|
-
_proc = Option::KW.(proc) do |type|
|
104
|
-
name = proc if type == :symbol
|
105
|
-
name = "#{proc.source_location[0].split("/").last}:#{proc.source_location.last}" if proc.is_a? Proc if type == :proc
|
106
|
-
name = proc.class if type == :callable
|
107
|
-
end
|
108
|
-
|
109
|
-
[ _proc, { name: name }.merge(options) ]
|
110
|
-
end
|
111
|
-
|
112
|
-
AddOptions = ->(decider_class, options) do
|
113
|
-
# for #failure and #success:
|
114
|
-
if decider_class == Stay::Decider
|
115
|
-
return [Stay, signal: Railway::FailFast] if options[:fail_fast]
|
116
|
-
return [Stay, signal: Railway::PassFast] if options[:pass_fast]
|
117
|
-
return [Stay, {}]
|
118
|
-
else # for #step:
|
119
|
-
return [Switch, decider_class: decider_class, on_false: Railway::FailFast] if options[:fail_fast]
|
120
|
-
return [Switch, decider_class: decider_class, on_true: Railway::PassFast] if options[:pass_fast]
|
121
|
-
return [Switch, decider_class: decider_class]
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end # DSL
|
125
|
-
end
|
126
|
-
|
127
|
-
require "uber/callable"
|
128
|
-
# Allows defining dependencies and inject/override them via runtime options, if desired.
|
129
|
-
class Pipetree::Step
|
130
|
-
include Uber::Callable
|
131
|
-
|
132
|
-
def initialize(step, dependencies={})
|
133
|
-
@step, @dependencies = step, dependencies
|
134
|
-
end
|
135
|
-
|
136
|
-
def call(input, options)
|
137
|
-
@dependencies.each { |k, v| options[k] ||= v } # not sure i like this, but the step's API is cool.
|
138
|
-
|
139
|
-
@step.(input, options)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|