trailblazer-operation 0.6.5 → 0.7.3
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 +4 -4
- data/.github/workflows/ci.yml +17 -0
- data/CHANGES.md +23 -0
- data/Gemfile +2 -1
- data/Rakefile +1 -12
- data/lib/trailblazer/operation/class_dependencies.rb +4 -4
- data/lib/trailblazer/operation/public_call.rb +39 -14
- data/lib/trailblazer/operation/trace.rb +5 -0
- data/lib/trailblazer/operation/version.rb +1 -1
- data/test/docs/macaroni_test.rb +27 -27
- data/test/docs/operation_test.rb +62 -2
- data/test/operation_test.rb +66 -0
- data/test/step_test.rb +21 -8
- data/test/trace_test.rb +24 -0
- data/trailblazer-operation.gemspec +2 -3
- metadata +11 -29
- data/.travis.yml +0 -13
- data/test/ruby-2.0.0/operation_test.rb +0 -61
- data/test/ruby-2.0.0/step_test.rb +0 -137
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2bed59ccc4a6af470ef0413dfd4c5132c138a2ed68e1e7ed390ea7637c8db4e
|
4
|
+
data.tar.gz: '074982e69ce025d63cc256964b8c334ad6405f792357201778beea2694668f93'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b74fd06391e9035c5a82ff85b281e4b87445f18b0c238d5f939dfdb80e4541cd484743523a474371dfa2dd803068c6bb415732a40bea25dfa67fd777134dc3c
|
7
|
+
data.tar.gz: 79eb31f4211e4a6521c3c06f879df49bf32b57f5b020b0f3a4273efb8c12fc047812f9a75f0987034c78fc6952945d5e4e24d08ac820b6c31222657490d4ea68
|
@@ -0,0 +1,17 @@
|
|
1
|
+
name: CI
|
2
|
+
on: [push, pull_request]
|
3
|
+
jobs:
|
4
|
+
test:
|
5
|
+
strategy:
|
6
|
+
fail-fast: false
|
7
|
+
matrix:
|
8
|
+
# Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0'
|
9
|
+
ruby: [2.5, 2.6, 2.7, '3.0', head, jruby, jruby-head]
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
steps:
|
12
|
+
- uses: actions/checkout@v2
|
13
|
+
- uses: ruby/setup-ruby@v1
|
14
|
+
with:
|
15
|
+
ruby-version: ${{ matrix.ruby }}
|
16
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
17
|
+
- run: bundle exec rake
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
## 0.7.3
|
2
|
+
|
3
|
+
* Revert trailblazer-developer to a runtime dependency.
|
4
|
+
|
5
|
+
## 0.7.2
|
6
|
+
|
7
|
+
* Bugfix: when calling `Operation.call(params: {}, "current_user" => user)` the stringified variables got lost in Ruby < 3.
|
8
|
+
|
9
|
+
## 0.7.1
|
10
|
+
|
11
|
+
* In `Operation.call_with_public_interface`, pass `self` and not `@activity` to the `invoke`r. This fixes tracing as it now catches the actual Operation class, not an activity instance.
|
12
|
+
|
13
|
+
## 0.7.0
|
14
|
+
|
15
|
+
* Compatible with Ruby 2.4-3.0.
|
16
|
+
* Add `Operation.wtf?`.
|
17
|
+
* Add `Operation.call_with_flow_options` to allow using explicit aliasing in Ruby < 3.0.
|
18
|
+
|
19
|
+
## 0.6.6
|
20
|
+
|
21
|
+
* Rename `Operation.flow_options` to `Operation.flow_options_for_public_call`.
|
22
|
+
* Operations can also accept `flow_options` at run-time now :beers:, giving them precedence over `Operation.flow_options_for_public_call`.
|
23
|
+
|
1
24
|
## 0.6.5
|
2
25
|
|
3
26
|
* Upgrade `trailblazer-activity` & `trailblazer-activity-dsl-linear` versions to utilise new `trailblazer-context` :drum:
|
data/Gemfile
CHANGED
@@ -10,8 +10,9 @@ gem "dry-auto_inject"
|
|
10
10
|
gem "benchmark-ips"
|
11
11
|
gem "minitest-line"
|
12
12
|
|
13
|
-
# gem "trailblazer-developer", path: "../developer"
|
13
|
+
# gem "trailblazer-developer", path: "../trailblazer-developer"
|
14
14
|
# gem "trailblazer-developer", git: "https://github.com/trailblazer/trailblazer-developer"
|
15
15
|
# gem "trailblazer-activity", path: "../trailblazer-activity"
|
16
|
+
# gem "trailblazer-context", path: "../trailblazer-context"
|
16
17
|
# gem "trailblazer-activity-dsl-linear", path: "../trailblazer-activity-dsl-linear"
|
17
18
|
# gem "trailblazer-activity", github: "trailblazer/trailblazer-activity"
|
data/Rakefile
CHANGED
@@ -4,18 +4,7 @@ require "rake/testtask"
|
|
4
4
|
Rake::TestTask.new(:test) do |test|
|
5
5
|
test.libs << "test"
|
6
6
|
test.verbose = true
|
7
|
-
|
8
|
-
test_files = FileList["test/**/*_test.rb"]
|
9
|
-
|
10
|
-
if RUBY_VERSION == "2.0.0"
|
11
|
-
# test_files = test_files - %w{test/dry_container_test.rb test/2.1.0-pipetree_test.rb}
|
12
|
-
test_files = test_files - %w{test/step_test.rb} + %w{test/ruby-2.0.0/step_test.rb}
|
13
|
-
test_files = test_files - %w{test/operation_test.rb} + %w{test/ruby-2.0.0/operation_test.rb}
|
14
|
-
else
|
15
|
-
test_files -= FileList["test/ruby-2.0.0/*"]
|
16
|
-
end
|
17
|
-
|
18
|
-
test.test_files = test_files
|
7
|
+
test.test_files = FileList["test/**/*_test.rb"]
|
19
8
|
end
|
20
9
|
|
21
10
|
task :default => %i[test]
|
@@ -12,9 +12,9 @@ class Trailblazer::Operation
|
|
12
12
|
@state.update_options(options)
|
13
13
|
end
|
14
14
|
|
15
|
-
def options_for_public_call(options,
|
15
|
+
def options_for_public_call(options, flow_options)
|
16
16
|
ctx = super
|
17
|
-
context_for_fields(class_fields, [ctx, flow_options]
|
17
|
+
context_for_fields(class_fields, [ctx, flow_options])
|
18
18
|
end
|
19
19
|
|
20
20
|
private def class_fields
|
@@ -26,9 +26,9 @@ class Trailblazer::Operation
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def call_with_circuit_interface((ctx, flow_options), **circuit_options)
|
29
|
-
ctx_with_fields = context_for_fields(class_fields, [ctx, flow_options], circuit_options)
|
29
|
+
ctx_with_fields = context_for_fields(class_fields, [ctx, flow_options], **circuit_options)
|
30
30
|
|
31
|
-
super([ctx_with_fields, flow_options], circuit_options) # FIXME: should we unwrap here?
|
31
|
+
super([ctx_with_fields, flow_options], **circuit_options) # FIXME: should we unwrap here?
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -13,21 +13,33 @@ module Trailblazer
|
|
13
13
|
#
|
14
14
|
# @note Do not override this method as it will be removed in future versions. Also, you will break tracing.
|
15
15
|
# @return Operation::Railway::Result binary result object
|
16
|
-
def call(options = {},
|
17
|
-
return call_with_circuit_interface(options,
|
16
|
+
def call(options = {}, flow_options = {}, **circuit_options)
|
17
|
+
return call_with_circuit_interface(options, **circuit_options) if options.is_a?(Array) # This is kind of a hack that could be well hidden if Ruby had method overloading. Goal is to simplify the call/__call__ thing as we're fading out Operation::call anyway.
|
18
18
|
|
19
|
-
call_with_public_interface(options,
|
19
|
+
call_with_public_interface(options, flow_options, **circuit_options)
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
# Default {@activity} call interface which doesn't accept {circuit_options}
|
23
|
+
#
|
24
|
+
# @param [Array] args => [ctx, flow_options]
|
25
|
+
#
|
26
|
+
# @return [Operation::Railway::Result]
|
27
|
+
#
|
28
|
+
# @private
|
29
|
+
def call_with_public_interface(options, flow_options, invoke_class: Activity::TaskWrap, **circuit_options)
|
30
|
+
flow_options = flow_options_for_public_call(flow_options)
|
31
|
+
|
32
|
+
# In Ruby < 3, calling Op.(params: {}, "current_user" => user) results in both {circuit_options} and {options} containing variables.
|
33
|
+
# In Ruby 3.0, **circuit_options is always empty.
|
34
|
+
options = circuit_options.any? ? circuit_options.merge(options) : options
|
35
|
+
|
36
|
+
ctx = options_for_public_call(options, flow_options)
|
24
37
|
|
25
38
|
# call the activity.
|
26
39
|
# This will result in invoking {::call_with_circuit_interface}.
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
[ctx, flow_options()],
|
40
|
+
signal, (ctx, flow_options) = invoke_class.invoke(
|
41
|
+
self,
|
42
|
+
[ctx, flow_options],
|
31
43
|
exec_context: new
|
32
44
|
)
|
33
45
|
|
@@ -36,8 +48,15 @@ module Trailblazer
|
|
36
48
|
end
|
37
49
|
|
38
50
|
# This interface is used for all nested OPs (and the outer-most, too).
|
39
|
-
|
40
|
-
|
51
|
+
#
|
52
|
+
# @param [Array] args - Contains [ctx, flow_options]
|
53
|
+
# @param [Hash] circuit_options - Options to configure activity circuit
|
54
|
+
#
|
55
|
+
# @return [signal, [ctx, flow_options]]
|
56
|
+
#
|
57
|
+
# @private
|
58
|
+
def call_with_circuit_interface(args, **circuit_options)
|
59
|
+
strategy_call(args, **circuit_options) # FastTrack#call
|
41
60
|
end
|
42
61
|
|
43
62
|
def options_for_public_call(*args)
|
@@ -46,13 +65,19 @@ module Trailblazer
|
|
46
65
|
|
47
66
|
# Compile a Context object to be passed into the Activity::call.
|
48
67
|
# @private
|
49
|
-
def self.options_for_public_call(options,
|
68
|
+
def self.options_for_public_call(options, flow_options = {})
|
50
69
|
Trailblazer::Context(options, {}, flow_options[:context_options])
|
51
70
|
end
|
52
71
|
|
53
72
|
# @semi=public
|
54
|
-
def
|
55
|
-
|
73
|
+
def flow_options_for_public_call(options = {})
|
74
|
+
options
|
75
|
+
end
|
76
|
+
|
77
|
+
# TODO: remove when we stop supporting < 3.0.
|
78
|
+
def call_with_flow_options(options, flow_options)
|
79
|
+
raise "[Trailblazer] `Operation.call_with_flow_options is deprecated in Ruby 3.0. Use `Operation.(options, flow_options)`" if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0.0")
|
80
|
+
call_with_public_interface(options, flow_options, {invoke_class: Activity::TaskWrap})
|
56
81
|
end
|
57
82
|
end
|
58
83
|
end
|
@@ -6,6 +6,7 @@ module Trailblazer
|
|
6
6
|
module Trace
|
7
7
|
# @note The problem in this method is, we have redundancy with Operation::PublicCall
|
8
8
|
def self.call(operation, options)
|
9
|
+
# warn %{Trailblazer: `Operation.trace` is deprecated. Please use `Operation.wtf?`.} # DISCUSS: should this be deprecated?
|
9
10
|
ctx = PublicCall.options_for_public_call(options) # redundant with PublicCall::call.
|
10
11
|
|
11
12
|
stack, signal, (ctx, _flow_options) = Developer::Trace.(operation, [ctx, {}])
|
@@ -25,6 +26,10 @@ module Trailblazer
|
|
25
26
|
Trace.(self, options)
|
26
27
|
end
|
27
28
|
|
29
|
+
def wtf?(options)
|
30
|
+
call_with_public_interface(options, {}, invoke_class: Developer::Wtf)
|
31
|
+
end
|
32
|
+
|
28
33
|
# Presentation of the traced stack via the returned result object.
|
29
34
|
# This object is wrapped around the original result in {Trace.call}.
|
30
35
|
class Result < ::SimpleDelegator
|
data/test/docs/macaroni_test.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
|
-
require "test_helper"
|
1
|
+
# require "test_helper"
|
2
2
|
|
3
|
-
class MacaroniTaskBuilderTest < Minitest::Spec
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
# class MacaroniTaskBuilderTest < Minitest::Spec
|
4
|
+
# Memo = Struct.new(:title) do
|
5
|
+
# def save
|
6
|
+
# self.title = title[:title].reverse
|
7
|
+
# end
|
8
|
+
# end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
# #:create
|
11
|
+
# class Memo::Create < Trailblazer::Operation(step_interface_builder: Trailblazer::Operation::Railway::KwSignature)
|
12
|
+
# #~ign
|
13
|
+
# step :create_model
|
14
|
+
# step :save
|
15
|
+
# #~ign end
|
16
|
+
# #~methods
|
17
|
+
# def create_model(params:, options:, **)
|
18
|
+
# options[:model] = Memo.new(title: params[:title])
|
19
|
+
# end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
# def save(model:, **)
|
22
|
+
# model.save
|
23
|
+
# end
|
24
|
+
# #~methods end
|
25
|
+
# end
|
26
|
+
# #:create end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
28
|
+
# it "allows optional macaroni call style" do
|
29
|
+
# Memo::Create.(params: {title: "Wow!"}).inspect(:model).must_equal %{<Result:true [#<struct MacaroniTaskBuilderTest::Memo title=\"!woW\">] >}
|
30
|
+
# end
|
31
|
+
# end
|
data/test/docs/operation_test.rb
CHANGED
@@ -24,7 +24,6 @@ class DocsActivityTest < Minitest::Spec
|
|
24
24
|
signal.inspect.must_equal %{#<Trailblazer::Activity::Railway::End::Success semantic=:success>}
|
25
25
|
end
|
26
26
|
|
27
|
-
#:describe
|
28
27
|
describe Memo::Create do
|
29
28
|
it "creates a sane Memo instance" do
|
30
29
|
#:call-public
|
@@ -39,8 +38,69 @@ class DocsActivityTest < Minitest::Spec
|
|
39
38
|
result.success?.must_equal true
|
40
39
|
result[:model].text.must_equal "Enjoy an IPA"
|
41
40
|
end
|
41
|
+
|
42
|
+
it "allows indifferent access for ctx keys" do
|
43
|
+
#:ctx-indifferent-access
|
44
|
+
result = Memo::Create.(params: { text: "Enjoy an IPA" })
|
45
|
+
|
46
|
+
result[:params] # => { text: "Enjoy an IPA" }
|
47
|
+
result['params'] # => { text: "Enjoy an IPA" }
|
48
|
+
#:ctx-indifferent-access end
|
49
|
+
|
50
|
+
result.success?.must_equal true
|
51
|
+
result[:params].must_equal({ text: "Enjoy an IPA" })
|
52
|
+
result['params'].must_equal({ text: "Enjoy an IPA" })
|
53
|
+
end
|
54
|
+
|
55
|
+
it "allows defining aliases for ctx keys" do
|
56
|
+
module AliasesExample
|
57
|
+
Memo = Struct.new(:text)
|
58
|
+
|
59
|
+
module Memo::Contract
|
60
|
+
Create = Struct.new(:sync)
|
61
|
+
end
|
62
|
+
|
63
|
+
#:ctx-aliases-step
|
64
|
+
class Memo::Create < Trailblazer::Operation
|
65
|
+
#~flow
|
66
|
+
step ->(ctx, **) { ctx[:'contract.default'] = Memo::Contract::Create.new }
|
67
|
+
#~flow end
|
68
|
+
|
69
|
+
pass :sync
|
70
|
+
|
71
|
+
def sync(ctx, contract:, **)
|
72
|
+
# ctx['contract.default'] == ctx[:contract]
|
73
|
+
contract.sync
|
74
|
+
end
|
75
|
+
end
|
76
|
+
#:ctx-aliases-step end
|
77
|
+
end
|
78
|
+
|
79
|
+
#:ctx-aliases
|
80
|
+
options = { params: { text: "Enjoy an IPA" } }
|
81
|
+
flow_options = {
|
82
|
+
context_options: {
|
83
|
+
aliases: { 'contract.default': :contract, 'policy.default': :policy },
|
84
|
+
container_class: Trailblazer::Context::Container::WithAliases,
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
# Sorry, this feature is only reliable in Ruby > 2.7
|
89
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0.0")
|
90
|
+
result = AliasesExample::Memo::Create.(options, flow_options)
|
91
|
+
else # Ruby 2.6 etc
|
92
|
+
result = AliasesExample::Memo::Create.call_with_flow_options(options, flow_options)
|
93
|
+
end
|
94
|
+
|
95
|
+
result['contract.default'] # => Memo::Contract::Create
|
96
|
+
result[:contract] # => Memo::Contract::Create
|
97
|
+
#:ctx-aliases end
|
98
|
+
|
99
|
+
result.success?.must_equal true
|
100
|
+
_(result[:contract].class).must_equal AliasesExample::Memo::Contract::Create
|
101
|
+
_(result['contract.default']).must_equal result[:contract]
|
102
|
+
end
|
42
103
|
end
|
43
|
-
#:describe end
|
44
104
|
|
45
105
|
it do
|
46
106
|
module J
|
data/test/operation_test.rb
CHANGED
@@ -79,8 +79,74 @@ class DeclarativeApiTest < Minitest::Spec
|
|
79
79
|
step ->(options, **) { options["e"] = 2 }
|
80
80
|
end
|
81
81
|
|
82
|
+
class Aliases < Update
|
83
|
+
def self.flow_options_for_public_call(*)
|
84
|
+
{
|
85
|
+
context_options: {
|
86
|
+
aliases: { 'b' => :settle },
|
87
|
+
container_class: Trailblazer::Context::Container::WithAliases,
|
88
|
+
}
|
89
|
+
}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
82
93
|
it "allows to inherit" do
|
83
94
|
Upsert.("params" => {decide: true}).inspect("a", "b", "c", "d", "e").must_equal %{<Result:true [false, true, nil, 1, nil] >}
|
84
95
|
Unset. ("params" => {decide: true}).inspect("a", "b", "c", "d", "e").must_equal %{<Result:true [false, true, nil, 1, 2] >}
|
85
96
|
end
|
97
|
+
|
98
|
+
# Mixing keywords and string keys in {Operation.call}.
|
99
|
+
# Test that {.(params: {}, "current_user" => user)} is processed properly
|
100
|
+
class Collect < Trailblazer::Operation
|
101
|
+
# step ->(ctx, **) { ctx[:keys] }
|
102
|
+
end
|
103
|
+
|
104
|
+
it "contains all keys from {call}" do
|
105
|
+
result = Collect.(params: {}, "current_user" => Module)
|
106
|
+
_(result.inspect).must_equal %{<Result:true #<Trailblazer::Context::Container wrapped_options={:params=>{}, \"current_user\"=>Module} mutable_options={}> >}
|
107
|
+
end
|
108
|
+
|
109
|
+
#---
|
110
|
+
#- ctx container
|
111
|
+
it do
|
112
|
+
options = { "params" => {decide: true} }
|
113
|
+
|
114
|
+
# Default call
|
115
|
+
result = Update.(options)
|
116
|
+
result.inspect("a", "b", "c").must_equal %{<Result:true [false, true, nil] >}
|
117
|
+
|
118
|
+
# Circuit interface call
|
119
|
+
signal, (ctx, _) = Update.([Update.options_for_public_call(options), {}], **{})
|
120
|
+
|
121
|
+
signal.inspect.must_equal %{#<Trailblazer::Activity::Railway::End::Success semantic=:success>}
|
122
|
+
ctx.inspect.must_equal %{#<Trailblazer::Context::Container wrapped_options={\"params\"=>{:decide=>true}} mutable_options={\"a\"=>false, \"b\"=>true}>}
|
123
|
+
|
124
|
+
# Call by passing aliases as an argument.
|
125
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.0.0")
|
126
|
+
result = Update.(
|
127
|
+
options,
|
128
|
+
{
|
129
|
+
context_options: {
|
130
|
+
aliases: { 'b' => :settle },
|
131
|
+
container_class: Trailblazer::Context::Container::WithAliases,
|
132
|
+
}
|
133
|
+
}
|
134
|
+
)
|
135
|
+
else
|
136
|
+
result = Update.call_with_flow_options(
|
137
|
+
options,
|
138
|
+
{
|
139
|
+
context_options: {
|
140
|
+
aliases: { 'b' => :settle },
|
141
|
+
container_class: Trailblazer::Context::Container::WithAliases,
|
142
|
+
}
|
143
|
+
},
|
144
|
+
)
|
145
|
+
end
|
146
|
+
|
147
|
+
result[:settle].must_equal true
|
148
|
+
# Set aliases by overriding `flow_options` at the compile time.
|
149
|
+
result = Aliases.(options)
|
150
|
+
result[:settle].must_equal true
|
151
|
+
end
|
86
152
|
end
|
data/test/step_test.rb
CHANGED
@@ -40,7 +40,11 @@ class StepTest < Minitest::Spec
|
|
40
40
|
|
41
41
|
it { Create.(a: 1, b: 2, c: 3, d: 4, e: 5).inspect("a", "b", "c", "d", "e").must_equal "<Result:true [1, 2, 3, 4, 5] >" }
|
42
42
|
|
43
|
-
|
43
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.7.0")
|
44
|
+
it { Trailblazer::Developer.railway(Create).gsub(/0x.+?step_test.rb/, "").gsub(/\)\s.+?step_test.rb/, ") test/step_test.rb").must_equal %{[>#<Proc::30 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c(options, c: ..., **) test/step_test.rb:18>,>d,>MyMacro]} }
|
45
|
+
else
|
46
|
+
it { Trailblazer::Developer.railway(Create).gsub(/0x.+?step_test.rb/, "").must_equal %{[>#<Proc::30 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c>,>d,>MyMacro]} }
|
47
|
+
end
|
44
48
|
|
45
49
|
#---
|
46
50
|
#- :before, :after, :replace, :delete, :override
|
@@ -174,11 +178,20 @@ class StepTest < Minitest::Spec
|
|
174
178
|
# not existent :name
|
175
179
|
it do
|
176
180
|
op = assert_raises Trailblazer::Activity::DSL::Linear::Sequence::IndexError do
|
177
|
-
|
181
|
+
class InvalidStep < Trailblazer::Operation
|
178
182
|
step :a, before: "I don't exist!"
|
179
183
|
end
|
180
184
|
end
|
181
|
-
|
185
|
+
|
186
|
+
error_message = %{#<Trailblazer::Activity::DSL::Linear::Sequence::IndexError: StepTest::InvalidStep:
|
187
|
+
\e[31m\"I don't exist!\" is not a valid step ID. Did you mean any of these ?\e[0m
|
188
|
+
\e[32m\"Start.default\"
|
189
|
+
\"End.success\"
|
190
|
+
\"End.pass_fast\"
|
191
|
+
\"End.fail_fast\"
|
192
|
+
\"End.failure\"\e[0m>}
|
193
|
+
|
194
|
+
assert_match error_message, op.inspect
|
182
195
|
end
|
183
196
|
|
184
197
|
#---
|
@@ -195,16 +208,16 @@ class StepTest < Minitest::Spec
|
|
195
208
|
|
196
209
|
#---
|
197
210
|
#- inheritance
|
198
|
-
class New <
|
211
|
+
class New < Index
|
199
212
|
end
|
200
213
|
|
201
|
-
it { Trailblazer::Developer.railway(New).
|
214
|
+
it { Trailblazer::Developer.railway(New).must_equal %{[>my validate,>persist!,>I win!,>No, I do!]} }
|
202
215
|
|
203
|
-
class Update <
|
204
|
-
step :after_save
|
216
|
+
class Update < Index
|
217
|
+
step :after_save
|
205
218
|
end
|
206
219
|
|
207
|
-
it { Trailblazer::Developer.railway(Update).
|
220
|
+
it { Trailblazer::Developer.railway(Update).must_equal %{[>my validate,>persist!,>I win!,>No, I do!,>after_save]} }
|
208
221
|
end
|
209
222
|
|
210
223
|
#---
|
data/test/trace_test.rb
CHANGED
@@ -49,4 +49,28 @@ class TraceTest < Minitest::Spec
|
|
49
49
|
|-- Create.task.params
|
50
50
|
`-- End.success}
|
51
51
|
end
|
52
|
+
|
53
|
+
it "Operation.wtf?" do
|
54
|
+
result = nil
|
55
|
+
output, = capture_io do
|
56
|
+
result = Create.wtf?(params: {x: 1}, a_return: true)
|
57
|
+
end
|
58
|
+
|
59
|
+
output.gsub(/0x\w+/, "").gsub(/@.+_test/, "").must_equal %{`-- TraceTest::Create
|
60
|
+
|-- \e[32mStart.default\e[0m
|
61
|
+
|-- \e[32mCreate.task.a\e[0m
|
62
|
+
|-- MyNested
|
63
|
+
| |-- \e[32mStart.default\e[0m
|
64
|
+
| |-- \e[32mB.task.b\e[0m
|
65
|
+
| |-- \e[32mB.task.e\e[0m
|
66
|
+
| `-- End.success
|
67
|
+
|-- \e[32mCreate.task.c\e[0m
|
68
|
+
|-- \e[32mCreate.task.params\e[0m
|
69
|
+
`-- End.success
|
70
|
+
}
|
71
|
+
|
72
|
+
result.success?.must_equal true
|
73
|
+
result[:a_return].must_equal true
|
74
|
+
result[:params].inspect.must_equal %{{:x=>1}}
|
75
|
+
end
|
52
76
|
end
|
@@ -17,9 +17,8 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_dependency "trailblazer-activity-dsl-linear", ">= 0.
|
21
|
-
spec.add_dependency "trailblazer-
|
22
|
-
spec.add_dependency "trailblazer-developer", ">= 0.0.8"
|
20
|
+
spec.add_dependency "trailblazer-activity-dsl-linear", ">= 0.4.0", "< 1.0.0"
|
21
|
+
spec.add_dependency "trailblazer-developer", ">= 0.0.21", "< 1.0.0"
|
23
22
|
|
24
23
|
spec.add_development_dependency "bundler"
|
25
24
|
spec.add_development_dependency "minitest"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trailblazer-operation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: trailblazer-activity-dsl-linear
|
@@ -16,7 +16,7 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.4.0
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: 1.0.0
|
@@ -26,17 +26,17 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.
|
29
|
+
version: 0.4.0
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 1.0.0
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
-
name: trailblazer-
|
34
|
+
name: trailblazer-developer
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 0.
|
39
|
+
version: 0.0.21
|
40
40
|
- - "<"
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: 1.0.0
|
@@ -46,24 +46,10 @@ dependencies:
|
|
46
46
|
requirements:
|
47
47
|
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 0.
|
49
|
+
version: 0.0.21
|
50
50
|
- - "<"
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: 1.0.0
|
53
|
-
- !ruby/object:Gem::Dependency
|
54
|
-
name: trailblazer-developer
|
55
|
-
requirement: !ruby/object:Gem::Requirement
|
56
|
-
requirements:
|
57
|
-
- - ">="
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: 0.0.8
|
60
|
-
type: :runtime
|
61
|
-
prerelease: false
|
62
|
-
version_requirements: !ruby/object:Gem::Requirement
|
63
|
-
requirements:
|
64
|
-
- - ">="
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version: 0.0.8
|
67
53
|
- !ruby/object:Gem::Dependency
|
68
54
|
name: bundler
|
69
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -127,10 +113,10 @@ executables: []
|
|
127
113
|
extensions: []
|
128
114
|
extra_rdoc_files: []
|
129
115
|
files:
|
116
|
+
- ".github/workflows/ci.yml"
|
130
117
|
- ".gitignore"
|
131
118
|
- ".rubocop.yml"
|
132
119
|
- ".rubocop_todo.yml"
|
133
|
-
- ".travis.yml"
|
134
120
|
- CHANGES.md
|
135
121
|
- Gemfile
|
136
122
|
- README.md
|
@@ -163,8 +149,6 @@ files:
|
|
163
149
|
- test/introspect_test.rb
|
164
150
|
- test/operation_test.rb
|
165
151
|
- test/result_test.rb
|
166
|
-
- test/ruby-2.0.0/operation_test.rb
|
167
|
-
- test/ruby-2.0.0/step_test.rb
|
168
152
|
- test/skill_test.rb
|
169
153
|
- test/step_test.rb
|
170
154
|
- test/test_helper.rb
|
@@ -177,7 +161,7 @@ homepage: http://trailblazer.to
|
|
177
161
|
licenses:
|
178
162
|
- MIT
|
179
163
|
metadata: {}
|
180
|
-
post_install_message:
|
164
|
+
post_install_message:
|
181
165
|
rdoc_options: []
|
182
166
|
require_paths:
|
183
167
|
- lib
|
@@ -193,7 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
193
177
|
version: '0'
|
194
178
|
requirements: []
|
195
179
|
rubygems_version: 3.0.8
|
196
|
-
signing_key:
|
180
|
+
signing_key:
|
197
181
|
specification_version: 4
|
198
182
|
summary: Trailblazer's operation object with railway flow and integrated error handling.
|
199
183
|
test_files:
|
@@ -215,8 +199,6 @@ test_files:
|
|
215
199
|
- test/introspect_test.rb
|
216
200
|
- test/operation_test.rb
|
217
201
|
- test/result_test.rb
|
218
|
-
- test/ruby-2.0.0/operation_test.rb
|
219
|
-
- test/ruby-2.0.0/step_test.rb
|
220
202
|
- test/skill_test.rb
|
221
203
|
- test/step_test.rb
|
222
204
|
- test/test_helper.rb
|
data/.travis.yml
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class DeclarativeApiTest < Minitest::Spec
|
4
|
-
#---
|
5
|
-
#- step, pass, fail
|
6
|
-
|
7
|
-
# Test: step/pass/fail
|
8
|
-
# * do they deviate properly?
|
9
|
-
class Create < Trailblazer::Operation
|
10
|
-
step :decide!
|
11
|
-
success :wasnt_ok!
|
12
|
-
success :was_ok!
|
13
|
-
failure :return_true!
|
14
|
-
failure :return_false!
|
15
|
-
|
16
|
-
def decide!(options, decide: raise, **_o)
|
17
|
-
options["a"] = true
|
18
|
-
decide
|
19
|
-
end
|
20
|
-
|
21
|
-
def wasnt_ok!(options, **_o)
|
22
|
-
options["y"] = false
|
23
|
-
end
|
24
|
-
|
25
|
-
def was_ok!(options, **_o)
|
26
|
-
options["x"] = true
|
27
|
-
end
|
28
|
-
|
29
|
-
def return_true!(options, **_o); options["b"] = true end
|
30
|
-
|
31
|
-
def return_false!(options, **_o); options["c"] = false end
|
32
|
-
end
|
33
|
-
|
34
|
-
it { Create.({}, decide: true).inspect("a", "x", "y", "b", "c").must_equal %{<Result:true [true, true, false, nil, nil] >} }
|
35
|
-
it { Create.({}, decide: false).inspect("a", "x", "y", "b", "c").must_equal %{<Result:false [true, nil, nil, true, false] >} }
|
36
|
-
|
37
|
-
#---
|
38
|
-
#- trace
|
39
|
-
|
40
|
-
it do
|
41
|
-
end
|
42
|
-
|
43
|
-
#---
|
44
|
-
#- empty class
|
45
|
-
class Noop < Trailblazer::Operation
|
46
|
-
end
|
47
|
-
|
48
|
-
it { Noop.().inspect("params").must_equal %{<Result:true [{}] >} }
|
49
|
-
|
50
|
-
#---
|
51
|
-
#- pass
|
52
|
-
#- fail
|
53
|
-
class Update < Trailblazer::Operation
|
54
|
-
pass ->(options, **_o) { options["a"] = false }
|
55
|
-
step ->(options, params: raise, **_o) { options["b"] = params[:decide] }
|
56
|
-
fail ->(options, **_o) { options["c"] = true }
|
57
|
-
end
|
58
|
-
|
59
|
-
it { Update.(decide: true).inspect("a", "b", "c").must_equal %{<Result:true [false, true, nil] >} }
|
60
|
-
it { Update.(decide: false).inspect("a", "b", "c").must_equal %{<Result:false [false, false, true] >} }
|
61
|
-
end
|
@@ -1,137 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
# Tests
|
4
|
-
# --- step ->(*o) { snippet }
|
5
|
-
# --- step Callable
|
6
|
-
# --- step :method
|
7
|
-
# --- step MyMacro
|
8
|
-
class StepTest < Minitest::Spec
|
9
|
-
class Callable
|
10
|
-
def self.call(options, b: nil, **_o)
|
11
|
-
options["b"] = b
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
module Implementation
|
16
|
-
module_function
|
17
|
-
|
18
|
-
def c(options, c: nil, **_o)
|
19
|
-
options["c"] = c
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
MyMacro = ->(direction, options, flow_options) do
|
24
|
-
options["e"] = options[:e]
|
25
|
-
|
26
|
-
[direction, options, flow_options]
|
27
|
-
end
|
28
|
-
|
29
|
-
class Create < Trailblazer::Operation
|
30
|
-
step ->(options, a: nil, **_o) { options["a"] = a }
|
31
|
-
step Callable
|
32
|
-
step Implementation.method(:c)
|
33
|
-
step :d
|
34
|
-
step [MyMacro, {}] # doesn't provide runner_options.
|
35
|
-
|
36
|
-
def d(options, d: nil, **_o)
|
37
|
-
options["d"] = d
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
it { Create.({}, a: 1, b: 2, c: 3, d: 4, e: 5).inspect("a", "b", "c", "d", "e").must_equal "<Result:true [1, 2, 3, 4, 5] >" }
|
42
|
-
|
43
|
-
it { Trailblazer::Operation::Inspect.(Create).gsub(/0x.+?step_test.rb/, "").must_equal %{[>#<Proc::29 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c>,>d,>[#<Proc::22 (lambda)>, {}]]} }
|
44
|
-
# poor test to make sure we pass debug information to Activity.
|
45
|
-
it { Create["__activity__"].graph.find_all(:d).first[:id].must_equal :d }
|
46
|
-
|
47
|
-
#---
|
48
|
-
#- :before, :after, :replace, :delete, :override
|
49
|
-
class A < Trailblazer::Operation
|
50
|
-
step :a!
|
51
|
-
def a!(options, **_o); options["a"] = 1; end
|
52
|
-
def a!(options, **_o); options["a"] = 1; end if RUBY_VERSION == "2.0.0"
|
53
|
-
end
|
54
|
-
|
55
|
-
class B < A
|
56
|
-
step :b!, before: :a!
|
57
|
-
step :c!, before: :a!
|
58
|
-
step :d!, after: :b!
|
59
|
-
end
|
60
|
-
|
61
|
-
it { Trailblazer::Operation::Inspect.(B).must_equal %{[>b!,>d!,>c!,>a!]} }
|
62
|
-
|
63
|
-
class C < B
|
64
|
-
step :e!, replace: :c!
|
65
|
-
step nil, delete: :d!
|
66
|
-
end
|
67
|
-
|
68
|
-
it { Trailblazer::Operation::Inspect.(C).must_equal %{[>b!,>e!,>a!]} }
|
69
|
-
|
70
|
-
class D < Trailblazer::Operation
|
71
|
-
step :a!
|
72
|
-
step :b!
|
73
|
-
step :b!, override: true
|
74
|
-
end
|
75
|
-
|
76
|
-
it { Trailblazer::Operation::Inspect.(D).must_equal %{[>a!,>b!]} }
|
77
|
-
|
78
|
-
# not existent :name
|
79
|
-
it do
|
80
|
-
err = assert_raises Trailblazer::Operation::Railway::Sequence::IndexError do
|
81
|
-
class E < Trailblazer::Operation
|
82
|
-
step :a, before: "I don't exist!"
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
err.inspect.must_equal "#<Trailblazer::Operation::Railway::Sequence::IndexError: I don't exist!>"
|
87
|
-
end
|
88
|
-
|
89
|
-
#---
|
90
|
-
#- :name
|
91
|
-
#- step :whatever, name: :validate
|
92
|
-
class Index < Trailblazer::Operation
|
93
|
-
step :validate!, name: "my validate"
|
94
|
-
step :persist!
|
95
|
-
step [MyMacro, name: "I win!"]
|
96
|
-
step [MyMacro, name: "I win!"], name: "No, I do!"
|
97
|
-
end
|
98
|
-
|
99
|
-
it { Trailblazer::Operation::Inspect.(Index).must_equal %{[>my validate,>persist!,>I win!,>No, I do!]} }
|
100
|
-
|
101
|
-
#---
|
102
|
-
#- inheritance
|
103
|
-
class New < Create
|
104
|
-
end
|
105
|
-
|
106
|
-
it { Trailblazer::Operation::Inspect.(New).gsub(/0x.+?step_test.rb/, "").must_equal %{[>#<Proc::29 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c>,>d,>[#<Proc::22 (lambda)>, {}]]} }
|
107
|
-
|
108
|
-
class Update < Create
|
109
|
-
step :after_save!
|
110
|
-
end
|
111
|
-
|
112
|
-
it { Trailblazer::Operation::Inspect.(Update).gsub(/0x.+?step_test.rb/, "").must_equal %{[>#<Proc::29 (lambda)>,>StepTest::Callable,>#<Method: StepTest::Implementation.c>,>d,>[#<Proc::22 (lambda)>, {}],>after_save!]} }
|
113
|
-
end
|
114
|
-
|
115
|
-
#---
|
116
|
-
#- Macros with the old `input` arg.
|
117
|
-
# step [ ->(input, options) { } ]
|
118
|
-
# TODO: remove me in 2.2.
|
119
|
-
class StepWithDeprecatedMacroTest < Minitest::Spec
|
120
|
-
class Create < Trailblazer::Operation
|
121
|
-
MyOutdatedMacro = ->(input, options) {
|
122
|
-
options["x"] = input.class
|
123
|
-
}
|
124
|
-
|
125
|
-
class AnotherOldMacro
|
126
|
-
def self.call(input, options)
|
127
|
-
options["y"] = input.class
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
step [MyOutdatedMacro, name: :outdated]
|
132
|
-
step [AnotherOldMacro, name: :oldie]
|
133
|
-
end
|
134
|
-
|
135
|
-
it { Trailblazer::Operation::Inspect.(Create).gsub(/0x.+?step_test.rb/, "").must_equal %{[>outdated,>oldie]} }
|
136
|
-
it { Create.().inspect("x", "y").must_equal %{<Result:true [StepWithDeprecatedMacroTest::Create, StepWithDeprecatedMacroTest::Create] >} }
|
137
|
-
end
|