trailblazer-operation 0.0.13 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +5 -3
- data/CHANGES.md +44 -0
- data/Gemfile +13 -2
- data/Rakefile +8 -6
- data/lib/trailblazer/operation.rb +86 -12
- data/lib/trailblazer/operation/deprecated_macro.rb +19 -0
- data/lib/trailblazer/operation/inject.rb +34 -0
- data/lib/trailblazer/operation/inspect.rb +80 -0
- data/lib/trailblazer/operation/public_call.rb +62 -0
- data/lib/trailblazer/operation/railway.rb +32 -0
- data/lib/trailblazer/operation/railway/fast_track.rb +13 -0
- data/lib/trailblazer/operation/railway/normalizer.rb +73 -0
- data/lib/trailblazer/operation/railway/task_builder.rb +44 -0
- data/lib/trailblazer/operation/result.rb +6 -4
- data/lib/trailblazer/operation/skill.rb +8 -24
- data/lib/trailblazer/operation/task_wrap.rb +68 -0
- data/lib/trailblazer/operation/trace.rb +49 -0
- data/lib/trailblazer/operation/variable_mapping.rb +91 -0
- data/lib/trailblazer/operation/version.rb +1 -1
- data/test/call_test.rb +27 -8
- data/test/class_dependencies_test.rb +16 -0
- data/test/docs/doormat_test.rb +189 -0
- data/test/docs/wiring_test.rb +421 -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 +50 -0
- data/test/macro_test.rb +61 -0
- data/test/operation_test.rb +94 -0
- data/test/result_test.rb +14 -8
- data/test/ruby-2.0.0/operation_test.rb +73 -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 +91 -0
- data/test/test_helper.rb +37 -0
- data/test/trace_test.rb +62 -0
- data/test/variable_mapping_test.rb +66 -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 +62 -36
- 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/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
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e11de8247c38298cb548d31fb21ca138949204da
|
4
|
+
data.tar.gz: fd3a2a39355bc6e064d174e098d542f69e8f0fbc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b65963cfacea4a758ee64ede04d7c67a6e84433503d0278ebf8e163509205c1a75360fad353a76a271eb2392f5bdeecba66faebe6d78438b6c9b9d1eda36834
|
7
|
+
data.tar.gz: e8edfcc04c39863635ee3123e90c9ea1a024240b61b54ea3356906a687c62a4929041949dad345f9e214ef104b4a6060d655d4461ecff637966d73c495e676a5
|
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,47 @@
|
|
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
|
+
## 0.1.0
|
18
|
+
|
19
|
+
inspect: failure is << and success is >>
|
20
|
+
|
21
|
+
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
|
22
|
+
|
23
|
+
FastTrack optional
|
24
|
+
Wrapped optional
|
25
|
+
|
26
|
+
* Add `pass` and `fail` as four-character aliases for `success` and `failure`.
|
27
|
+
* Remove `Uber::Callable` requirement and treat all non-`:symbol` steps as callable objects.
|
28
|
+
* Remove non-kw options for steps. All steps receive keyword args now:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
def model(options)
|
32
|
+
```
|
33
|
+
|
34
|
+
now must have a minimal signature as follows.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
def model(options, **)
|
38
|
+
```
|
39
|
+
* Remove `Operation#[]` and `Operation#[]=`. Please only change state in `options`.
|
40
|
+
* 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.
|
41
|
+
* Remove support for Ruby 1.9.3 for now. This can be re-introduced on demand.
|
42
|
+
* Remove `pipetree` in favor of [`trailblazer-circuit`](https://github.com/trailblazer/trailblazer-circuit). This allows rich workflows and state machines in an operation.
|
43
|
+
* Remove `uber` dependency.
|
44
|
+
|
1
45
|
## 0.0.13
|
2
46
|
|
3
47
|
* Rename `Operation::New` to `:Instantiate` to avoid name clashes with `New` operations in applications.
|
data/Gemfile
CHANGED
@@ -9,5 +9,16 @@ gem "dry-auto_inject"
|
|
9
9
|
|
10
10
|
gem "minitest-line"
|
11
11
|
gem "benchmark-ips"
|
12
|
-
|
13
|
-
# gem "
|
12
|
+
|
13
|
+
# gem "trailblazer-circuit", git: "https://github.com/trailblazer/trailblazer-circuit"
|
14
|
+
# gem "trailblazer-activity", path: "../trailblazer-activity"
|
15
|
+
# gem "trailblazer-developer", path: "../developer"
|
16
|
+
gem "trailblazer-developer", git: "https://github.com/trailblazer/trailblazer-developer"
|
17
|
+
# gem "representable", path: "../representable"
|
18
|
+
|
19
|
+
# gem "raise", path: "../raise"
|
20
|
+
|
21
|
+
# gem "declarative", path: "../declarative"
|
22
|
+
|
23
|
+
gem "trailblazer-activity", path: "../circuit"
|
24
|
+
# gem "trailblazer-activity", git: "https://github.com/trailblazer/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,98 @@
|
|
1
1
|
require "forwardable"
|
2
|
-
|
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/magnetic"
|
10
|
+
require "trailblazer/activity/wrap"
|
11
|
+
|
12
|
+
require "trailblazer/operation/variable_mapping"
|
13
|
+
|
14
|
+
require "trailblazer/operation/public_call" # TODO: Remove in 3.0.
|
3
15
|
require "trailblazer/operation/skill"
|
4
|
-
require "trailblazer/operation/
|
5
|
-
require "trailblazer/operation/
|
16
|
+
require "trailblazer/operation/deprecated_macro" # TODO: remove in 2.2.
|
17
|
+
require "trailblazer/operation/result"
|
18
|
+
require "trailblazer/operation/railway"
|
19
|
+
|
20
|
+
require "trailblazer/operation/railway/task_builder"
|
21
|
+
require "trailblazer/operation/railway/fast_track"
|
22
|
+
require "trailblazer/operation/railway/normalizer"
|
23
|
+
require "trailblazer/operation/task_wrap"
|
24
|
+
require "trailblazer/operation/trace"
|
6
25
|
|
7
26
|
module Trailblazer
|
8
27
|
# The Trailblazer-style operation.
|
9
28
|
# Note that you don't have to use our "opinionated" version with result object, skills, etc.
|
10
29
|
class Operation
|
11
|
-
extend
|
12
|
-
|
30
|
+
extend Skill::Accessors # ::[] and ::[]= # TODO: fade out this usage.
|
31
|
+
|
32
|
+
def self.inherited(subclass)
|
33
|
+
super
|
34
|
+
subclass.initialize!
|
35
|
+
heritage.(subclass)
|
36
|
+
end
|
37
|
+
|
38
|
+
module Process
|
39
|
+
def initialize!
|
40
|
+
initialize_activity_dsl!
|
41
|
+
recompile_process!
|
42
|
+
end
|
43
|
+
|
44
|
+
# builder is stateless, it's up to you to save @adds somewhere.
|
45
|
+
def initialize_activity_dsl!
|
46
|
+
builder_options = {
|
47
|
+
track_end: Railway::End::Success.new(:success, semantic: :success),
|
48
|
+
failure_end: Railway::End::Failure.new(:failure, semantic: :failure),
|
49
|
+
pass_fast_end: Railway::End::PassFast.new(:pass_fast, semantic: :pass_fast),
|
50
|
+
fail_fast_end: Railway::End::FailFast.new(:fail_fast, semantic: :fail_fast),
|
51
|
+
}
|
52
|
+
|
53
|
+
@builder, @adds = Activity::Magnetic::Builder::FastTrack.for( Railway::Normalizer, builder_options )
|
54
|
+
@debug = {}
|
55
|
+
end
|
13
56
|
|
14
|
-
|
57
|
+
def recompile_process!
|
58
|
+
@process, @outputs = Activity::Recompile.( @adds )
|
59
|
+
end
|
15
60
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
extend Skill::Call::Positional # ::call(params, options)
|
61
|
+
def outputs
|
62
|
+
@outputs
|
63
|
+
end
|
20
64
|
|
21
|
-
|
22
|
-
|
65
|
+
include Activity::Interface
|
66
|
+
|
67
|
+
# Call the actual {Process} with the options prepared in PublicCall.
|
68
|
+
def __call__(args, circuit_options={})
|
69
|
+
@process.( args, circuit_options.merge( exec_context: new ) )
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
extend Process # make ::call etc. class methods on Operation.
|
74
|
+
|
75
|
+
extend Activity::Heritage::Accessor
|
76
|
+
|
77
|
+
extend Activity::DSL # #_task
|
78
|
+
# delegate step, pass and fail via Operation::_task to the @builder, and save results in @adds.
|
79
|
+
extend Activity::DSL.def_dsl! :step
|
80
|
+
extend Activity::DSL.def_dsl! :pass
|
81
|
+
extend Activity::DSL.def_dsl! :fail
|
82
|
+
class << self
|
83
|
+
alias_method :success, :pass
|
84
|
+
alias_method :failure, :fail
|
85
|
+
|
86
|
+
extend Forwardable # TODO: test those helpers
|
87
|
+
def_delegators :@builder, :Path, :Output, :End #, :task
|
88
|
+
end
|
89
|
+
|
90
|
+
extend PublicCall # ::call(params, { current_user: .. })
|
91
|
+
extend Trace # ::trace
|
92
|
+
|
93
|
+
|
94
|
+
include Railway::TaskWrap
|
23
95
|
end
|
24
96
|
end
|
97
|
+
|
98
|
+
require "trailblazer/operation/inspect"
|
@@ -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 = Operation::Railway::TaskBuilder.binary_direction_for(result, Activity::Right, Activity::Left)
|
12
|
+
|
13
|
+
return direction, [options, flow_options]
|
14
|
+
end
|
15
|
+
|
16
|
+
return wrapped_proc, options
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,34 @@
|
|
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
|
+
Activity::Magnetic::Builder::Path.plan do
|
10
|
+
task ReverseMergeDefaults.new( default_dependencies ),
|
11
|
+
id: "ReverseMergeDefaults#{default_dependencies}",
|
12
|
+
before: "task_wrap.call_task"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
# @returns Task
|
18
|
+
# @param Hash list of key/value that should be set if not already assigned/set before (or injected from the outside).
|
19
|
+
class ReverseMergeDefaults
|
20
|
+
def initialize(defaults)
|
21
|
+
@defaults = defaults
|
22
|
+
end
|
23
|
+
|
24
|
+
def call((wrap_ctx, original_args), **circuit_options)
|
25
|
+
ctx = original_args[0][0]
|
26
|
+
|
27
|
+
@defaults.each { |k, v| ctx[k] ||= v }
|
28
|
+
|
29
|
+
return Activity::Right, [ wrap_ctx, original_args ]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end # Inject
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,80 @@
|
|
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
|
+
adds = operation.instance_variable_get(:@adds)
|
21
|
+
alterations = Activity::Magnetic::Builder::Finalizer.adds_to_alterations(adds)
|
22
|
+
# DISCUSS: any other way to retrieve the Alterations?
|
23
|
+
|
24
|
+
# pp alterations
|
25
|
+
railway = alterations.instance_variable_get(:@groups).instance_variable_get(:@groups)[:main]
|
26
|
+
|
27
|
+
rows = railway.each_with_index.collect do |element, i|
|
28
|
+
magnetic_to, task, plus_poles = element.configuration
|
29
|
+
|
30
|
+
created_by =
|
31
|
+
if magnetic_to == [:failure]
|
32
|
+
:fail
|
33
|
+
elsif plus_poles.size > 1
|
34
|
+
plus_poles[0].color == plus_poles[1].color ? :pass : :step
|
35
|
+
else
|
36
|
+
:pass # this is wrong for Nested, sometimes
|
37
|
+
end
|
38
|
+
|
39
|
+
[ i, [ created_by, element.id ] ]
|
40
|
+
end
|
41
|
+
|
42
|
+
return inspect_line(rows) if options[:style] == :line
|
43
|
+
return inspect_rows(rows)
|
44
|
+
end
|
45
|
+
|
46
|
+
def inspect_func(step)
|
47
|
+
@inspect[step]
|
48
|
+
end
|
49
|
+
|
50
|
+
Operator = { :fail => "<<", :pass => ">>", :step => ">"}
|
51
|
+
|
52
|
+
def inspect_line(names)
|
53
|
+
string = names.collect { |i, (end_of_edge, name)| "#{Operator[end_of_edge]}#{name}" }.join(",")
|
54
|
+
"[#{string}]"
|
55
|
+
end
|
56
|
+
|
57
|
+
def inspect_rows(names)
|
58
|
+
string = names.collect do |i, (end_of_edge, name)|
|
59
|
+
operator = Operator[end_of_edge]
|
60
|
+
|
61
|
+
op = "#{operator}#{name}"
|
62
|
+
padding = 38
|
63
|
+
|
64
|
+
proc = if operator == "<<"
|
65
|
+
sprintf("%- #{padding}s", op)
|
66
|
+
elsif [">", ">>", "&"].include?(operator.to_s)
|
67
|
+
sprintf("% #{padding}s", op)
|
68
|
+
else
|
69
|
+
pad = " " * ((padding - op.length) / 2)
|
70
|
+
"#{pad}#{op}#{pad}"
|
71
|
+
end
|
72
|
+
|
73
|
+
proc = proc.gsub(" ", "=")
|
74
|
+
|
75
|
+
sprintf("%2d %s", i, proc)
|
76
|
+
end.join("\n")
|
77
|
+
"\n#{string}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class Trailblazer::Operation
|
2
|
+
module PublicCall
|
3
|
+
# This is the outer-most public `call` method that gets invoked when calling `Create.()`.
|
4
|
+
# The signature of this is `params, options, *containers`. This was a mistake, as the
|
5
|
+
# first argument could've been part of `options` hash in the first place.
|
6
|
+
#
|
7
|
+
# Create.(params, runtime_data, *containers)
|
8
|
+
# #=> Result<Context...>
|
9
|
+
#
|
10
|
+
# In workflows/Nested compositions, this method is not used anymore and it might probably
|
11
|
+
# get removed in future versions of TRB. Currently, we use Operation::__call__ as an alternative.
|
12
|
+
#
|
13
|
+
# @return Operation::Railway::Result binary result object
|
14
|
+
def call(*args)
|
15
|
+
ctx = PublicCall.options_for_public_call(*args)
|
16
|
+
|
17
|
+
# call the activity.
|
18
|
+
last_signal, (options, flow_options) = __call__( [ctx, {}] ) # Railway::call # DISCUSS: this could be ::call_with_context.
|
19
|
+
|
20
|
+
# Result is successful if the activity ended with an End event derived from Railway::End::Success.
|
21
|
+
Railway::Result(last_signal, options, flow_options)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
# Compile a Context object to be passed into the Activity::call.
|
26
|
+
def self.options_for_public_call(options={}, *containers)
|
27
|
+
# options, *containers = Deprecations.accept_positional_options(params, options, *containers) # TODO: make this optional for "power users".
|
28
|
+
|
29
|
+
# generate the skill hash that embraces runtime options plus potential containers, the so called Runtime options.
|
30
|
+
# This wrapping is supposed to happen once in the entire system.
|
31
|
+
|
32
|
+
hash_transformer = ->(containers) { containers[0].to_hash } # FIXME: don't transform any containers into kw args.
|
33
|
+
|
34
|
+
immutable_options = Trailblazer::Context::ContainerChain.new( [options, *containers], to_hash: hash_transformer ) # Runtime options, immutable.
|
35
|
+
|
36
|
+
ctx = Trailblazer::Context(immutable_options)
|
37
|
+
end
|
38
|
+
|
39
|
+
module Deprecations
|
40
|
+
# Merge the first argument to the public Create.() into the second.
|
41
|
+
#
|
42
|
+
# DISCUSS: this is experimental since we can never know whether the call is the old or new API.
|
43
|
+
#
|
44
|
+
# The following situations are _not_ covered here:
|
45
|
+
# * You're using a Hash instance as a container.
|
46
|
+
# * You're using more than one container.
|
47
|
+
#
|
48
|
+
# If you do so (we're assuming you know what you're doing then), please update your `call`s.
|
49
|
+
def self.accept_positional_options( *args )
|
50
|
+
if args.size == 1 && args[0].instance_of?(Hash) # new style, you're doing it right.
|
51
|
+
args
|
52
|
+
elsif args.size == 2 && args[0].instance_of?(Hash) && !args[1].instance_of?(Hash) # new style with container, you're doing it right.
|
53
|
+
args
|
54
|
+
else
|
55
|
+
warn "[Trailblazer] Passing two positional arguments to `Operation.( params, current_user: .. )` is deprecated. Please use one hash like `Operation.( params: params, current_user: .. )`"
|
56
|
+
params, options, *containers = args
|
57
|
+
[ options.merge("params" => params), *containers ]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Trailblazer
|
2
|
+
# Operations is simply a thin API to define, inherit and run circuits by passing the options object.
|
3
|
+
# It encourages the linear railway style (http://trb.to/gems/workflow/circuit.html#operation) but can
|
4
|
+
# easily be extend for more complex workflows.
|
5
|
+
class Operation
|
6
|
+
# End event: All subclasses of End:::Success are interpreted as "success".
|
7
|
+
module Railway
|
8
|
+
# @param options Context
|
9
|
+
# @param end_event The last emitted signal in a circuit is usually the end event.
|
10
|
+
def self.Result(end_event, options, *)
|
11
|
+
Result.new(end_event.kind_of?(End::Success), options, end_event)
|
12
|
+
end
|
13
|
+
|
14
|
+
# The Railway::Result knows about its binary state, the context (data), and the last event in the circuit.
|
15
|
+
class Result < Result # Operation::Result
|
16
|
+
def initialize(success, data, event)
|
17
|
+
super(success, data)
|
18
|
+
|
19
|
+
@event = event
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :event
|
23
|
+
end
|
24
|
+
|
25
|
+
module End
|
26
|
+
class Success < Activity::End; end
|
27
|
+
class Failure < Activity::End; end
|
28
|
+
end
|
29
|
+
|
30
|
+
end # Railway
|
31
|
+
end
|
32
|
+
end
|