trailblazer-macro 2.1.0.rc13 → 2.1.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/.travis.yml +9 -8
- data/CHANGES.md +22 -0
- data/LICENSE +9 -0
- data/lib/trailblazer/macro.rb +12 -13
- data/lib/trailblazer/macro/model.rb +9 -3
- data/lib/trailblazer/macro/rescue.rb +1 -1
- data/lib/trailblazer/macro/version.rb +1 -1
- data/lib/trailblazer/macro/wrap.rb +3 -1
- data/test/docs/guard_test.rb +8 -5
- data/test/docs/model_test.rb +20 -0
- data/test/docs/nested_test.rb +110 -29
- data/test/docs/rescue_test.rb +1 -1
- data/test/docs/wrap_test.rb +216 -78
- data/test/operation/model_test.rb +2 -5
- data/test/test_helper.rb +4 -3
- data/trailblazer-macro.gemspec +5 -7
- metadata +34 -15
- data/LICENSE.txt +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05d8aa98a836c3309c0d44fca95f9bad68c025b7e3358b5e2029ac3f065ad58a
|
4
|
+
data.tar.gz: 9d19baf7edee2388ae99741628729bbafb7d6eb77b09c0baebc19b7e884349f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5a1336a619916dc0397595a24671b8c7fcfb765fc39ccdb74a07898bf667b51a808f85cdd595916c0a15db4ffba7103cd2922545ca6d5d432d8015316581990
|
7
|
+
data.tar.gz: d9f939b6d3f3521b255de73efb4a27ce7baa7aadd4a25d7766e5adcf224a6fb0241882736306123f879b8d0821d7710f177eb233e65f39459a5afae5dea6e210
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
# 2.1.3
|
2
|
+
|
3
|
+
* Rename Model()'s `not_found_end` kwarg to `not_found_terminus` for consistency.
|
4
|
+
|
5
|
+
# 2.1.2
|
6
|
+
|
7
|
+
* Fix to make macros available in all Linear::DSL strategies.
|
8
|
+
* Make `params` optional in `Model`.
|
9
|
+
* Support for adding `End.not_found` end in `Model`.
|
10
|
+
|
11
|
+
# 2.1.1
|
12
|
+
|
13
|
+
* Fix case when Macros generate same id due to small entropy
|
14
|
+
|
15
|
+
# 2.1.0
|
16
|
+
|
17
|
+
* Finally.
|
18
|
+
|
19
|
+
# 2.1.0.rc14
|
20
|
+
|
21
|
+
* Remove the explicit `dsl-linear` dependency.
|
22
|
+
|
1
23
|
# 2.1.0.rc13
|
2
24
|
|
3
25
|
* Use symbol keys on `ctx`, only.
|
data/LICENSE
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
Copyright (c) 2018 Trailblazer GmbH
|
2
|
+
|
3
|
+
Trailblazer is an Open Source project licensed under the terms of
|
4
|
+
the LGPLv3 license. Please see <http://www.gnu.org/licenses/lgpl-3.0.html>
|
5
|
+
for license text.
|
6
|
+
|
7
|
+
Trailblazer PRO has a commercial-friendly license allowing private forks
|
8
|
+
and modifications of Trailblazer. Please see http://trailblazer.to/pro for
|
9
|
+
more detail.
|
data/lib/trailblazer/macro.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
require "forwardable"
|
1
2
|
require "trailblazer/activity"
|
2
|
-
require "trailblazer/activity/dsl/linear"
|
3
|
+
require "trailblazer/activity/dsl/linear"
|
3
4
|
require "trailblazer/operation" # TODO: remove this dependency
|
4
5
|
|
5
6
|
require "trailblazer/macro/model"
|
@@ -12,18 +13,16 @@ require "trailblazer/macro/wrap"
|
|
12
13
|
|
13
14
|
module Trailblazer
|
14
15
|
module Macro
|
15
|
-
# All macros sit in the {Trailblazer::Macro} namespace, where we forward calls from
|
16
|
-
# operations and activities to.
|
17
|
-
def self.forward_macros(target)
|
18
|
-
target.singleton_class.def_delegators Trailblazer::Macro, :Model, :Wrap, :Rescue, :Nested
|
19
|
-
target.const_set(:Policy, Trailblazer::Macro::Policy)
|
20
|
-
end
|
21
16
|
end
|
22
|
-
end
|
23
17
|
|
24
|
-
#
|
25
|
-
#
|
26
|
-
|
18
|
+
# All macros sit in the {Trailblazer::Macro} namespace, where we forward calls from
|
19
|
+
# operations and activities to.
|
20
|
+
module Activity::DSL::Linear::Helper
|
21
|
+
Policy = Trailblazer::Macro::Policy
|
27
22
|
|
28
|
-
|
29
|
-
|
23
|
+
module ClassMethods
|
24
|
+
extend Forwardable
|
25
|
+
def_delegators Trailblazer::Macro, :Model, :Nested, :Wrap, :Rescue
|
26
|
+
end # ClassMethods
|
27
|
+
end # Helper
|
28
|
+
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module Trailblazer::Macro
|
2
|
-
|
2
|
+
|
3
|
+
Linear = Trailblazer::Activity::DSL::Linear
|
4
|
+
|
5
|
+
def self.Model(model_class, action = nil, find_by_key = nil, id: 'model.build', not_found_terminus: false)
|
3
6
|
task = Trailblazer::Activity::TaskBuilder::Binary(Model.new)
|
4
7
|
|
5
8
|
injection = Trailblazer::Activity::TaskWrap::Inject::Defaults::Extension(
|
@@ -8,11 +11,14 @@ module Trailblazer::Macro
|
|
8
11
|
:"model.find_by_key" => find_by_key
|
9
12
|
)
|
10
13
|
|
11
|
-
{task: task, id:
|
14
|
+
options = { task: task, id: id, extensions: [injection] }
|
15
|
+
options = options.merge(Linear::Output(:failure) => Linear::End(:not_found)) if not_found_terminus
|
16
|
+
|
17
|
+
options
|
12
18
|
end
|
13
19
|
|
14
20
|
class Model
|
15
|
-
def call(options, params
|
21
|
+
def call(options, params: nil, **)
|
16
22
|
builder = Model::Builder.new
|
17
23
|
options[:model] = model = builder.call(options, params)
|
18
24
|
options[:"result.model"] = result = Trailblazer::Operation::Result.new(!model.nil?, {})
|
@@ -1,6 +1,8 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
1
3
|
module Trailblazer
|
2
4
|
module Macro
|
3
|
-
def self.Wrap(user_wrap, id: "Wrap/#{
|
5
|
+
def self.Wrap(user_wrap, id: "Wrap/#{SecureRandom.hex(4)}", &block)
|
4
6
|
activity = Class.new(Activity::FastTrack, &block) # This is currently coupled to {dsl-linear}.
|
5
7
|
|
6
8
|
outputs = activity.to_h[:outputs]
|
data/test/docs/guard_test.rb
CHANGED
@@ -6,13 +6,13 @@ class DocsGuardProcTest < Minitest::Spec
|
|
6
6
|
#:proc
|
7
7
|
class Create < Trailblazer::Operation
|
8
8
|
step Policy::Guard(->(options, pass:, **) { pass })
|
9
|
-
|
9
|
+
#:pipeonly
|
10
10
|
step :process
|
11
11
|
|
12
12
|
def process(options, **)
|
13
13
|
options[:x] = true
|
14
14
|
end
|
15
|
-
|
15
|
+
#:pipeonly end
|
16
16
|
end
|
17
17
|
#:proc end
|
18
18
|
|
@@ -46,13 +46,15 @@ class DocsGuardTest < Minitest::Spec
|
|
46
46
|
#:callable-op
|
47
47
|
class Create < Trailblazer::Operation
|
48
48
|
step Policy::Guard( MyGuard.new )
|
49
|
-
|
49
|
+
#:pipe-only
|
50
50
|
step :process
|
51
51
|
|
52
|
+
#~methods
|
52
53
|
def process(options, **)
|
53
54
|
options[:x] = true
|
54
55
|
end
|
55
|
-
#~
|
56
|
+
#~methods end
|
57
|
+
#:pipe-only end
|
56
58
|
end
|
57
59
|
#:callable-op end
|
58
60
|
|
@@ -72,10 +74,11 @@ class DocsGuardMethodTest < Minitest::Spec
|
|
72
74
|
end
|
73
75
|
#~pipe-onlyy
|
74
76
|
step :process
|
75
|
-
|
77
|
+
#~methods
|
76
78
|
def process(options, **)
|
77
79
|
options[:x] = true
|
78
80
|
end
|
81
|
+
#~methods end
|
79
82
|
#~pipe-onlyy end
|
80
83
|
end
|
81
84
|
#:method end
|
data/test/docs/model_test.rb
CHANGED
@@ -45,6 +45,13 @@ class DocsModelTest < Minitest::Spec
|
|
45
45
|
end
|
46
46
|
#:update-with-find-by-key end
|
47
47
|
|
48
|
+
#:update-with-not-found-end
|
49
|
+
class UpdateFailureWithModelNotFound < Trailblazer::Operation
|
50
|
+
step Model( Song, :find_by, not_found_terminus: true )
|
51
|
+
# ..
|
52
|
+
end
|
53
|
+
#:update-with-not-found-end end
|
54
|
+
|
48
55
|
it do
|
49
56
|
#:update-ok
|
50
57
|
result = Update.(params: { id: 1 })
|
@@ -83,6 +90,19 @@ class DocsModelTest < Minitest::Spec
|
|
83
90
|
result.success?.must_equal false
|
84
91
|
end
|
85
92
|
|
93
|
+
it do
|
94
|
+
#:update-with-not-found-end-use
|
95
|
+
result = UpdateFailureWithModelNotFound.(params: {title: nil})
|
96
|
+
result[:model] #=> nil
|
97
|
+
result.success? #=> false
|
98
|
+
result.event #=> #<Trailblazer::Activity::End semantic=:not_found>
|
99
|
+
#:update-with-not-found-end-use end
|
100
|
+
|
101
|
+
result[:model].must_be_nil
|
102
|
+
result.success?.must_equal false
|
103
|
+
result.event.inspect.must_equal %{#<Trailblazer::Activity::End semantic=:not_found>}
|
104
|
+
end
|
105
|
+
|
86
106
|
#:show
|
87
107
|
class Show < Trailblazer::Operation
|
88
108
|
step Model( Song, :[] )
|
data/test/docs/nested_test.rb
CHANGED
@@ -16,22 +16,33 @@ class NestedInput < Minitest::Spec
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
step Nested( edit )
|
25
|
-
step :b
|
26
|
-
|
27
|
-
include T.def_steps(:a, :b)
|
28
|
-
end
|
19
|
+
class Validate < Trailblazer::Operation
|
20
|
+
step :validate
|
21
|
+
# ... more steps ...
|
22
|
+
include T.def_steps(:validate)
|
23
|
+
end
|
29
24
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
25
|
+
it "Nested(Edit), without any options" do
|
26
|
+
module A
|
27
|
+
|
28
|
+
create =
|
29
|
+
#:nested
|
30
|
+
class Create < Trailblazer::Operation
|
31
|
+
step :create
|
32
|
+
step Nested(Validate)
|
33
|
+
step :save
|
34
|
+
#~meths
|
35
|
+
include T.def_steps(:create, :save)
|
36
|
+
#~meths end
|
37
|
+
end
|
38
|
+
#:nested end
|
39
|
+
|
40
|
+
# this will print a DEPRECATION warning.
|
41
|
+
# success
|
42
|
+
create.(seq: []).inspect(:seq).must_equal %{<Result:true [[:create, :validate, :save]] >}
|
43
|
+
# failure in Nested
|
44
|
+
create.(seq: [], validate: false).inspect(:seq).must_equal %{<Result:false [[:create, :validate]] >}
|
45
|
+
end
|
35
46
|
end
|
36
47
|
|
37
48
|
it "Nested(Edit), with Output rewiring" do
|
@@ -52,32 +63,102 @@ class NestedInput < Minitest::Spec
|
|
52
63
|
end
|
53
64
|
|
54
65
|
it "Nested(:method)" do
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
66
|
+
module B
|
67
|
+
create =
|
68
|
+
#:nested-dynamic
|
69
|
+
class Create < Trailblazer::Operation
|
70
|
+
step :create
|
71
|
+
step Nested(:compute_nested)
|
72
|
+
step :save
|
73
|
+
|
74
|
+
def compute_nested(ctx, params:, **)
|
75
|
+
params.is_a?(Hash) ? Validate : JsonValidate
|
76
|
+
end
|
77
|
+
#~meths
|
78
|
+
include T.def_steps(:create, :save)
|
79
|
+
#~meths end
|
62
80
|
end
|
81
|
+
#:nested-dynamic end
|
63
82
|
|
64
|
-
|
65
|
-
|
66
|
-
|
83
|
+
class JsonValidate < Validate
|
84
|
+
step :json
|
85
|
+
include T.def_steps(:json)
|
86
|
+
end
|
67
87
|
# `edit` and `update` can be called from Nested()
|
68
88
|
|
69
89
|
# edit/success
|
70
|
-
create.(seq: [],
|
90
|
+
create.(seq: [], params: {}).inspect(:seq).must_equal %{<Result:true [[:create, :validate, :save]] >}
|
71
91
|
|
72
92
|
# update/success
|
73
|
-
create.(seq: [],
|
93
|
+
create.(seq: [], params: nil).inspect(:seq).must_equal %{<Result:true [[:create, :validate, :json, :save]] >}
|
74
94
|
|
75
95
|
|
76
96
|
# wiring of fail:
|
77
97
|
# edit/failure
|
78
|
-
create.(seq: [],
|
98
|
+
create.(seq: [], params: {}, validate: false).inspect(:seq).must_equal %{<Result:false [[:create, :validate]] >}
|
79
99
|
# update/failure
|
80
|
-
create.(seq: [],
|
100
|
+
create.(seq: [], params: nil, json: false).inspect(:seq).must_equal %{<Result:false [[:create, :validate, :json]] >}
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it "Nested(:method), input: :my_input" do
|
105
|
+
module C
|
106
|
+
#:nested-dynamic
|
107
|
+
class Create < Trailblazer::Operation
|
108
|
+
step :create
|
109
|
+
step Nested(:compute_nested), input: ->(ctx, *) {{foo: :bar, seq: ctx[:seq]}}
|
110
|
+
step :save
|
111
|
+
|
112
|
+
def compute_nested(ctx, params:, **)
|
113
|
+
params.is_a?(Hash) ? Validate : JsonValidate
|
114
|
+
end
|
115
|
+
|
116
|
+
#~meths
|
117
|
+
include T.def_steps(:create, :save)
|
118
|
+
#~meths end
|
119
|
+
end
|
120
|
+
#:nested-dynamic end
|
121
|
+
|
122
|
+
class JsonValidate < Validate
|
123
|
+
step :json
|
124
|
+
include T.def_steps(:json)
|
125
|
+
end
|
126
|
+
|
127
|
+
# `edit` and `update` can be called from Nested()
|
128
|
+
end
|
129
|
+
|
130
|
+
C::Create.(seq: [], params: {}).inspect(:seq).must_equal %{<Result:true [[:create, :validate, :save]] >}
|
131
|
+
C::Create.(seq: [], params: nil).inspect(:seq).must_equal %{<Result:true [[:create, :validate, :json, :save]] >}
|
132
|
+
end
|
133
|
+
|
134
|
+
it "Nested(:method), with pass_fast returned from nested" do
|
135
|
+
class JustPassFast < Trailblazer::Operation
|
136
|
+
step :just_pass_fast, pass_fast: true
|
137
|
+
include T.def_steps(:just_pass_fast)
|
138
|
+
end
|
139
|
+
|
140
|
+
module D
|
141
|
+
|
142
|
+
create =
|
143
|
+
#:nested-with-pass-fast
|
144
|
+
class Create < Trailblazer::Operation
|
145
|
+
|
146
|
+
def compute_nested(ctx, **)
|
147
|
+
JustPassFast
|
148
|
+
end
|
149
|
+
|
150
|
+
step :create
|
151
|
+
step Nested(:compute_nested)
|
152
|
+
step :save
|
153
|
+
#~meths
|
154
|
+
include T.def_steps(:create, :save)
|
155
|
+
#~meths end
|
156
|
+
end
|
157
|
+
#:nested-with-pass-fast end
|
158
|
+
|
159
|
+
# pass fast
|
160
|
+
create.(seq: []).inspect(:seq).must_equal %{<Result:true [[:create, :just_pass_fast, :save]] >}
|
161
|
+
end
|
81
162
|
end
|
82
163
|
|
83
164
|
let(:compute_edit) {
|
data/test/docs/rescue_test.rb
CHANGED
@@ -23,7 +23,7 @@ class NestedRescueTest < Minitest::Spec
|
|
23
23
|
fail ->(options, **) { options["outer-err"] = true }, id: "nested/failure"
|
24
24
|
end
|
25
25
|
|
26
|
-
it { Trailblazer::Developer.railway(NestedInsanity).must_match /\[>Rescue\(\
|
26
|
+
it { Trailblazer::Developer.railway(NestedInsanity).must_match /\[>Rescue\(.{8}\),>nested/ } # FIXME: better introspect tests for all id-generating macros.
|
27
27
|
it { NestedInsanity.().inspect("a", "y", "z", "b", "c", "e", "inner-err", "outer-err").must_equal %{<Result:true [true, true, true, true, true, true, nil, nil] >} }
|
28
28
|
it { NestedInsanity.( "raise-y" => true).inspect("a", "y", "z", "b", "c", "e", "inner-err", "outer-err").must_equal %{<Result:false [true, true, nil, nil, nil, nil, true, true] >} }
|
29
29
|
it { NestedInsanity.( "raise-a" => true).inspect("a", "y", "z", "b", "c", "e", "inner-err", "outer-err").must_equal %{<Result:false [true, true, true, true, nil, nil, nil, true] >} }
|
data/test/docs/wrap_test.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
3
|
class DocsWrapTest < Minitest::Spec
|
4
|
-
module Memo
|
5
|
-
end
|
6
|
-
|
7
4
|
=begin
|
8
5
|
When success: return the block's returns
|
9
6
|
When raise: return {Railway.fail!}
|
@@ -11,11 +8,10 @@ When raise: return {Railway.fail!}
|
|
11
8
|
#:wrap-handler
|
12
9
|
class HandleUnsafeProcess
|
13
10
|
def self.call((ctx, flow_options), *, &block)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
11
|
+
yield # calls the wrapped steps
|
12
|
+
rescue
|
13
|
+
ctx[:exception] = $!.message
|
14
|
+
[ Trailblazer::Operation::Railway.fail!, [ctx, flow_options] ]
|
19
15
|
end
|
20
16
|
end
|
21
17
|
#:wrap-handler end
|
@@ -64,6 +60,11 @@ result.wtf? #=>
|
|
64
60
|
=end
|
65
61
|
end
|
66
62
|
|
63
|
+
=begin
|
64
|
+
Writing into ctx in a Wrap()
|
65
|
+
=end
|
66
|
+
it { Memo::Create.( { seq: [], rehash_raise: true } )[:exception].must_equal("nope!") }
|
67
|
+
|
67
68
|
=begin
|
68
69
|
When success: return the block's returns
|
69
70
|
When raise: return {Railway.fail!}, but wire Wrap() to {fail_fast: true}
|
@@ -74,13 +75,9 @@ When raise: return {Railway.fail!}, but wire Wrap() to {fail_fast: true}
|
|
74
75
|
class Memo::Create < Trailblazer::Operation
|
75
76
|
class HandleUnsafeProcess
|
76
77
|
def self.call((ctx), *, &block)
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
puts $!
|
81
|
-
ctx[:exception] = $!.message
|
82
|
-
[ Trailblazer::Operation::Railway.fail!, [ctx, {}] ]
|
83
|
-
end
|
78
|
+
yield # calls the wrapped steps
|
79
|
+
rescue
|
80
|
+
[ Trailblazer::Operation::Railway.fail!, [ctx, {}] ]
|
84
81
|
end
|
85
82
|
end
|
86
83
|
|
@@ -112,11 +109,9 @@ When raise: return {Railway.fail_fast!} and configure Wrap() to {fast_track: t
|
|
112
109
|
#:fail-fast-handler
|
113
110
|
class HandleUnsafeProcess
|
114
111
|
def self.call((ctx), *, &block)
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
[ Trailblazer::Operation::Railway.fail_fast!, [ctx, {}] ]
|
119
|
-
end
|
112
|
+
yield # calls the wrapped steps
|
113
|
+
rescue
|
114
|
+
[ Trailblazer::Operation::Railway.fail_fast!, [ctx, {}] ]
|
120
115
|
end
|
121
116
|
end
|
122
117
|
#:fail-fast-handler end
|
@@ -145,120 +140,176 @@ When raise: return {Railway.fail_fast!} and configure Wrap() to {fast_track: t
|
|
145
140
|
When success: return the block's returns
|
146
141
|
When raise: return {Railway.fail!} or {Railway.pass!}
|
147
142
|
=end
|
148
|
-
class
|
149
|
-
Memo
|
143
|
+
class WrapWithCustomEndsTest < Minitest::Spec
|
144
|
+
Memo = Module.new
|
150
145
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
146
|
+
#:custom-handler
|
147
|
+
class MyTransaction
|
148
|
+
MyFailSignal = Class.new(Trailblazer::Activity::Signal)
|
149
|
+
|
150
|
+
def self.call((ctx, flow_options), *, &block)
|
151
|
+
yield # calls the wrapped steps
|
152
|
+
rescue
|
153
|
+
MyFailSignal
|
159
154
|
end
|
160
155
|
end
|
156
|
+
#:custom-handler end
|
161
157
|
|
162
|
-
#:
|
163
|
-
class
|
164
|
-
|
165
|
-
|
158
|
+
#:custom
|
159
|
+
class Memo::Create < Trailblazer::Operation
|
160
|
+
step :find_model
|
161
|
+
step Wrap( MyTransaction ) {
|
162
|
+
step :update
|
163
|
+
step :rehash
|
164
|
+
},
|
165
|
+
Output(:success) => End(:transaction_worked),
|
166
|
+
Output(MyTransaction::MyFailSignal, :failure) => End(:transaction_failed)
|
167
|
+
step :notify
|
168
|
+
fail :log_error
|
169
|
+
#~methods
|
170
|
+
include T.def_steps(:find_model, :update, :notify, :log_error)
|
171
|
+
include Rehash
|
172
|
+
#~methods end
|
173
|
+
end
|
174
|
+
#:custom end
|
166
175
|
|
167
|
-
|
176
|
+
it do
|
177
|
+
result = Memo::Create.( { seq: [] } )
|
178
|
+
result.inspect(:seq).must_equal %{<Result:false [[:find_model, :update, :rehash]] >}
|
179
|
+
result.event.inspect.must_equal %{#<Trailblazer::Activity::End semantic=:transaction_worked>}
|
180
|
+
end
|
168
181
|
|
169
|
-
|
170
|
-
|
182
|
+
it do
|
183
|
+
result = Memo::Create.( { seq: [], rehash_raise: true } )
|
184
|
+
result.inspect(:seq).must_equal %{<Result:false [[:find_model, :update, :rehash]] >}
|
185
|
+
result.event.inspect.must_equal %{#<Trailblazer::Activity::End semantic=:transaction_failed>}
|
171
186
|
end
|
172
|
-
|
187
|
+
end
|
188
|
+
|
189
|
+
=begin
|
190
|
+
When success: return the block's returns
|
191
|
+
When raise: return {Railway.pass!} and go "successful"
|
192
|
+
=end
|
193
|
+
class WrapGoesIntoPassFromRescueTest < Minitest::Spec
|
194
|
+
Memo = Module.new
|
173
195
|
|
174
|
-
#:transaction
|
175
196
|
class Memo::Create < Trailblazer::Operation
|
197
|
+
class HandleUnsafeProcess
|
198
|
+
def self.call((ctx), *, &block)
|
199
|
+
yield # calls the wrapped steps
|
200
|
+
rescue
|
201
|
+
[ Trailblazer::Operation::Railway.pass!, [ctx, {}] ]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
176
205
|
step :find_model
|
177
|
-
step Wrap(
|
206
|
+
step Wrap( HandleUnsafeProcess ) {
|
178
207
|
step :update
|
179
208
|
step :rehash
|
180
209
|
}
|
181
210
|
step :notify
|
182
211
|
fail :log_error
|
212
|
+
|
183
213
|
#~methods
|
184
214
|
include T.def_steps(:find_model, :update, :notify, :log_error)
|
185
215
|
include Rehash
|
186
216
|
#~methods end
|
187
217
|
end
|
188
|
-
#:transaction end
|
189
218
|
|
190
219
|
it { Memo::Create.( { seq: [] } ).inspect(:seq).must_equal %{<Result:true [[:find_model, :update, :rehash, :notify]] >} }
|
191
|
-
it { Memo::Create.( { seq: [], rehash_raise: true } ).inspect(:seq).must_equal %{<Result:
|
220
|
+
it { Memo::Create.( { seq: [], rehash_raise: true } ).inspect(:seq).must_equal %{<Result:true [[:find_model, :update, :rehash, :notify]] >} }
|
192
221
|
end
|
193
222
|
|
194
223
|
=begin
|
195
224
|
When success: return the block's returns
|
196
|
-
When raise: return {
|
225
|
+
When raise: return {true} and go "successful"
|
226
|
+
You can return boolean true in wrap.
|
197
227
|
=end
|
198
|
-
class
|
199
|
-
Memo
|
200
|
-
Sequel = WrapWithTransactionTest::Sequel
|
228
|
+
class WrapGoesIntoBooleanTrueFromRescueTest < Minitest::Spec
|
229
|
+
Memo = Module.new
|
201
230
|
|
202
|
-
|
203
|
-
|
204
|
-
|
231
|
+
class Memo::Create < Trailblazer::Operation
|
232
|
+
class HandleUnsafeProcess
|
233
|
+
def self.call((ctx), *, &block)
|
234
|
+
yield # calls the wrapped steps
|
235
|
+
rescue
|
236
|
+
true
|
237
|
+
end
|
238
|
+
end
|
205
239
|
|
206
|
-
|
207
|
-
|
240
|
+
step :find_model
|
241
|
+
step Wrap( HandleUnsafeProcess ) {
|
242
|
+
step :update
|
243
|
+
step :rehash
|
244
|
+
}
|
245
|
+
step :notify
|
246
|
+
fail :log_error
|
208
247
|
|
209
|
-
|
248
|
+
#~methods
|
249
|
+
include T.def_steps(:find_model, :update, :notify, :log_error)
|
250
|
+
include Rehash
|
251
|
+
#~methods end
|
252
|
+
end
|
210
253
|
|
211
|
-
|
212
|
-
|
254
|
+
it "translates true returned form a wrap to a signal with a `success` semantic" do
|
255
|
+
result = Memo::Create.( { seq: [], rehash_raise: true } )
|
256
|
+
result.inspect(:seq).must_equal %{<Result:true [[:find_model, :update, :rehash, :notify]] >}
|
257
|
+
result.event.inspect.must_equal %{#<Trailblazer::Activity::Railway::End::Success semantic=:success>}
|
213
258
|
end
|
214
|
-
|
259
|
+
end
|
260
|
+
|
261
|
+
=begin
|
262
|
+
When success: return the block's returns
|
263
|
+
When raise: return {false} and go "failed"
|
264
|
+
You can return boolean false in wrap.
|
265
|
+
=end
|
266
|
+
class WrapGoesIntoBooleanFalseFromRescueTest < Minitest::Spec
|
267
|
+
Memo = Module.new
|
215
268
|
|
216
|
-
#:custom
|
217
269
|
class Memo::Create < Trailblazer::Operation
|
270
|
+
class HandleUnsafeProcess
|
271
|
+
def self.call((ctx), *, &block)
|
272
|
+
yield # calls the wrapped steps
|
273
|
+
rescue
|
274
|
+
false
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
218
278
|
step :find_model
|
219
|
-
step Wrap(
|
279
|
+
step Wrap( HandleUnsafeProcess ) {
|
220
280
|
step :update
|
221
281
|
step :rehash
|
222
|
-
}
|
223
|
-
Output(:success) => End(:transaction_worked),
|
224
|
-
Output(MyTransaction::MyFailSignal, :failure) => End(:transaction_failed)
|
282
|
+
}
|
225
283
|
step :notify
|
226
284
|
fail :log_error
|
285
|
+
|
227
286
|
#~methods
|
228
287
|
include T.def_steps(:find_model, :update, :notify, :log_error)
|
229
288
|
include Rehash
|
230
289
|
#~methods end
|
231
290
|
end
|
232
|
-
#:custom end
|
233
|
-
|
234
|
-
it do
|
235
|
-
result = Memo::Create.( { seq: [] } )
|
236
|
-
result.inspect(:seq).must_equal %{<Result:false [[:find_model, :update, :rehash]] >}
|
237
|
-
result.event.inspect.must_equal %{#<Trailblazer::Activity::End semantic=:transaction_worked>}
|
238
|
-
end
|
239
291
|
|
240
|
-
it do
|
292
|
+
it "translates false returned form a wrap to a signal with a `failure` semantic" do
|
241
293
|
result = Memo::Create.( { seq: [], rehash_raise: true } )
|
242
|
-
result.inspect(:seq).must_equal %{<Result:false [[:find_model, :update, :rehash]] >}
|
243
|
-
result.event.inspect.must_equal %{#<Trailblazer::Activity::End semantic=:
|
294
|
+
result.inspect(:seq).must_equal %{<Result:false [[:find_model, :update, :rehash, :log_error]] >}
|
295
|
+
result.event.inspect.must_equal %{#<Trailblazer::Activity::Railway::End::Failure semantic=:failure>}
|
244
296
|
end
|
245
297
|
end
|
246
298
|
|
247
299
|
=begin
|
248
300
|
When success: return the block's returns
|
249
|
-
When raise: return {
|
301
|
+
When raise: return {nil} and go "failed"
|
302
|
+
You can return nil in wrap.
|
250
303
|
=end
|
251
|
-
class
|
304
|
+
class WrapGoesIntoNilFromRescueTest < Minitest::Spec
|
252
305
|
Memo = Module.new
|
253
306
|
|
254
307
|
class Memo::Create < Trailblazer::Operation
|
255
308
|
class HandleUnsafeProcess
|
256
309
|
def self.call((ctx), *, &block)
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
[ Trailblazer::Operation::Railway.pass!, [ctx, {}] ]
|
261
|
-
end
|
310
|
+
yield # calls the wrapped steps
|
311
|
+
rescue
|
312
|
+
nil
|
262
313
|
end
|
263
314
|
end
|
264
315
|
|
@@ -276,7 +327,94 @@ When raise: return {Railway.pass!} and go "successful"
|
|
276
327
|
#~methods end
|
277
328
|
end
|
278
329
|
|
330
|
+
it "translates nil returned form a wrap to a signal with a `failure` semantic" do
|
331
|
+
result = Memo::Create.( { seq: [], rehash_raise: true } )
|
332
|
+
result.inspect(:seq).must_equal %{<Result:false [[:find_model, :update, :rehash, :log_error]] >}
|
333
|
+
result.event.inspect.must_equal %{#<Trailblazer::Activity::Railway::End::Failure semantic=:failure>}
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
=begin
|
338
|
+
When success: return the block's returns
|
339
|
+
When raise: return {Railway.fail!}
|
340
|
+
This one is mostly to show how one could wrap steps in a transaction
|
341
|
+
=end
|
342
|
+
class WrapWithTransactionTest < Minitest::Spec
|
343
|
+
Memo = Module.new
|
344
|
+
|
345
|
+
module Sequel
|
346
|
+
def self.transaction
|
347
|
+
end_event, (ctx, flow_options) = yield
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
#:transaction-handler
|
352
|
+
class MyTransaction
|
353
|
+
def self.call((ctx, flow_options), *, &block)
|
354
|
+
Sequel.transaction { yield } # calls the wrapped steps
|
355
|
+
rescue
|
356
|
+
[ Trailblazer::Operation::Railway.fail!, [ctx, flow_options] ]
|
357
|
+
end
|
358
|
+
end
|
359
|
+
#:transaction-handler end
|
360
|
+
|
361
|
+
#:transaction
|
362
|
+
class Memo::Create < Trailblazer::Operation
|
363
|
+
step :find_model
|
364
|
+
step Wrap( MyTransaction ) {
|
365
|
+
step :update
|
366
|
+
step :rehash
|
367
|
+
}
|
368
|
+
step :notify
|
369
|
+
fail :log_error
|
370
|
+
#~methods
|
371
|
+
include T.def_steps(:find_model, :update, :notify, :log_error)
|
372
|
+
include Rehash
|
373
|
+
#~methods end
|
374
|
+
end
|
375
|
+
#:transaction end
|
376
|
+
|
279
377
|
it { Memo::Create.( { seq: [] } ).inspect(:seq).must_equal %{<Result:true [[:find_model, :update, :rehash, :notify]] >} }
|
280
|
-
it { Memo::Create.( { seq: [], rehash_raise: true } ).inspect(:seq).must_equal %{<Result:
|
378
|
+
it { Memo::Create.( { seq: [], rehash_raise: true } ).inspect(:seq).must_equal %{<Result:false [[:find_model, :update, :rehash, :log_error]] >} }
|
379
|
+
end
|
380
|
+
|
381
|
+
=begin
|
382
|
+
When success: return {Railway.pass_fast!}
|
383
|
+
When failure: return {Railway.fail!}
|
384
|
+
This one is mostly to show how one could evaluate Wrap()'s return value based on Wrap() block's return
|
385
|
+
=end
|
386
|
+
class WrapWithBlockReturnSignatureCheckTest < Minitest::Spec
|
387
|
+
Memo = Module.new
|
388
|
+
|
389
|
+
#:handler-with-signature-evaluator
|
390
|
+
class HandleUnsafeProcess
|
391
|
+
def self.call((_ctx, _flow_options), *, &block)
|
392
|
+
signal, (ctx, flow_options) = yield
|
393
|
+
evaluated_signal = if signal.to_h[:semantic] == :success
|
394
|
+
Trailblazer::Operation::Railway.pass_fast!
|
395
|
+
else
|
396
|
+
Trailblazer::Operation::Railway.fail!
|
397
|
+
end
|
398
|
+
[ evaluated_signal, [ctx, flow_options] ]
|
399
|
+
end
|
400
|
+
end
|
401
|
+
#:handler-with-signature-evaluator end
|
402
|
+
|
403
|
+
#:transaction
|
404
|
+
class Memo::Create < Trailblazer::Operation
|
405
|
+
step :find_model
|
406
|
+
step Wrap( HandleUnsafeProcess ) {
|
407
|
+
step :update
|
408
|
+
}, fast_track: true # because Wrap can return pass_fast! now
|
409
|
+
step :notify
|
410
|
+
fail :log_error
|
411
|
+
#~methods
|
412
|
+
include T.def_steps(:find_model, :update, :notify, :log_error)
|
413
|
+
#~methods end
|
414
|
+
end
|
415
|
+
#:transaction end
|
416
|
+
|
417
|
+
it { Memo::Create.( { seq: [] } ).inspect(:seq).must_equal %{<Result:true [[:find_model, :update]] >} }
|
418
|
+
it { Memo::Create.( { seq: [], update: false } ).inspect(:seq).must_equal %{<Result:false [[:find_model, :update, :log_error]] >} }
|
281
419
|
end
|
282
420
|
end
|
@@ -19,11 +19,8 @@ class ModelTest < Minitest::Spec
|
|
19
19
|
end
|
20
20
|
|
21
21
|
# :new new.
|
22
|
-
it
|
23
|
-
|
24
|
-
|
25
|
-
result = Create.(params: {})
|
26
|
-
|
22
|
+
it "initializes new model's instance" do
|
23
|
+
result = Create.()
|
27
24
|
result[:model].inspect.must_equal %{#<struct ModelTest::Song id=nil, title=nil>}
|
28
25
|
end
|
29
26
|
|
data/test/test_helper.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require "trailblazer/macro"
|
3
|
+
|
1
4
|
require "delegate" # Ruby 2.2
|
2
5
|
require "minitest/autorun"
|
3
6
|
|
4
7
|
require "trailblazer/developer"
|
5
|
-
require "trailblazer/macro"
|
6
|
-
|
7
8
|
|
8
9
|
module Mock
|
9
10
|
class Result
|
@@ -39,7 +40,7 @@ T = Trailblazer::Activity::Testing
|
|
39
40
|
module Rehash
|
40
41
|
def rehash(ctx, seq:, rehash_raise: false, **)
|
41
42
|
seq << :rehash
|
42
|
-
raise if rehash_raise
|
43
|
+
raise "nope!" if rehash_raise
|
43
44
|
true
|
44
45
|
end
|
45
46
|
end
|
data/trailblazer-macro.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.description = "Macros for Trailblazer's operation"
|
11
11
|
spec.summary = "Macros for Trailblazer's operation: Policy, Wrap, Rescue and more."
|
12
12
|
spec.homepage = "http://trailblazer.to"
|
13
|
-
spec.license = "
|
13
|
+
spec.license = "LGPL-3.0"
|
14
14
|
|
15
15
|
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
16
16
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
@@ -18,9 +18,6 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
20
|
spec.add_development_dependency "bundler"
|
21
|
-
|
22
|
-
# spec.add_development_dependency "trailblazer-operation", ">= 0.4.1", "< 0.5.0"
|
23
|
-
|
24
21
|
spec.add_development_dependency "minitest"
|
25
22
|
spec.add_development_dependency "rake"
|
26
23
|
|
@@ -28,8 +25,9 @@ Gem::Specification.new do |spec|
|
|
28
25
|
spec.add_development_dependency "roar"
|
29
26
|
spec.add_development_dependency "trailblazer-developer"
|
30
27
|
|
31
|
-
spec.add_dependency "trailblazer-activity
|
32
|
-
spec.add_dependency "trailblazer-
|
28
|
+
spec.add_dependency "trailblazer-activity", ">= 0.10.0", "< 1.0.0"
|
29
|
+
spec.add_dependency "trailblazer-activity-dsl-linear", ">= 0.2.7", "< 1.0.0"
|
30
|
+
spec.add_dependency "trailblazer-operation", ">= 0.6.2" # TODO: this dependency will be removed.
|
33
31
|
|
34
|
-
spec.required_ruby_version = ">= 2.
|
32
|
+
spec.required_ruby_version = ">= 2.2.0"
|
35
33
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trailblazer-macro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2020-07-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -95,40 +95,60 @@ dependencies:
|
|
95
95
|
- - ">="
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: trailblazer-activity
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 0.10.0
|
105
|
+
- - "<"
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: 1.0.0
|
108
|
+
type: :runtime
|
109
|
+
prerelease: false
|
110
|
+
version_requirements: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: 0.10.0
|
115
|
+
- - "<"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.0.0
|
98
118
|
- !ruby/object:Gem::Dependency
|
99
119
|
name: trailblazer-activity-dsl-linear
|
100
120
|
requirement: !ruby/object:Gem::Requirement
|
101
121
|
requirements:
|
102
122
|
- - ">="
|
103
123
|
- !ruby/object:Gem::Version
|
104
|
-
version: 0.
|
124
|
+
version: 0.2.7
|
105
125
|
- - "<"
|
106
126
|
- !ruby/object:Gem::Version
|
107
|
-
version: 0.
|
127
|
+
version: 1.0.0
|
108
128
|
type: :runtime
|
109
129
|
prerelease: false
|
110
130
|
version_requirements: !ruby/object:Gem::Requirement
|
111
131
|
requirements:
|
112
132
|
- - ">="
|
113
133
|
- !ruby/object:Gem::Version
|
114
|
-
version: 0.
|
134
|
+
version: 0.2.7
|
115
135
|
- - "<"
|
116
136
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.
|
137
|
+
version: 1.0.0
|
118
138
|
- !ruby/object:Gem::Dependency
|
119
139
|
name: trailblazer-operation
|
120
140
|
requirement: !ruby/object:Gem::Requirement
|
121
141
|
requirements:
|
122
142
|
- - ">="
|
123
143
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.
|
144
|
+
version: 0.6.2
|
125
145
|
type: :runtime
|
126
146
|
prerelease: false
|
127
147
|
version_requirements: !ruby/object:Gem::Requirement
|
128
148
|
requirements:
|
129
149
|
- - ">="
|
130
150
|
- !ruby/object:Gem::Version
|
131
|
-
version: 0.
|
151
|
+
version: 0.6.2
|
132
152
|
description: Macros for Trailblazer's operation
|
133
153
|
email:
|
134
154
|
- apotonick@gmail.com
|
@@ -143,7 +163,7 @@ files:
|
|
143
163
|
- ".travis.yml"
|
144
164
|
- CHANGES.md
|
145
165
|
- Gemfile
|
146
|
-
- LICENSE
|
166
|
+
- LICENSE
|
147
167
|
- README.md
|
148
168
|
- Rakefile
|
149
169
|
- lib/trailblazer-macro.rb
|
@@ -170,7 +190,7 @@ files:
|
|
170
190
|
- trailblazer-macro.gemspec
|
171
191
|
homepage: http://trailblazer.to
|
172
192
|
licenses:
|
173
|
-
-
|
193
|
+
- LGPL-3.0
|
174
194
|
metadata: {}
|
175
195
|
post_install_message:
|
176
196
|
rdoc_options: []
|
@@ -180,15 +200,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
180
200
|
requirements:
|
181
201
|
- - ">="
|
182
202
|
- !ruby/object:Gem::Version
|
183
|
-
version: 2.
|
203
|
+
version: 2.2.0
|
184
204
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
205
|
requirements:
|
186
|
-
- - "
|
206
|
+
- - ">="
|
187
207
|
- !ruby/object:Gem::Version
|
188
|
-
version:
|
208
|
+
version: '0'
|
189
209
|
requirements: []
|
190
|
-
|
191
|
-
rubygems_version: 2.7.6
|
210
|
+
rubygems_version: 3.0.8
|
192
211
|
signing_key:
|
193
212
|
specification_version: 4
|
194
213
|
summary: 'Macros for Trailblazer''s operation: Policy, Wrap, Rescue and more.'
|
data/LICENSE.txt
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
The MIT License (MIT)
|
2
|
-
|
3
|
-
Copyright (c) 2018 Trailblazer GmbH
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
13
|
-
all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|
22
|
-
|
23
|
-
---------
|
24
|
-
|
25
|
-
Trailblazer Enterprise has a commercial-friendly license allowing private forks
|
26
|
-
and modifications of Trailblazer. Please see http://trailblazer.to/enterprise/ for
|
27
|
-
more detail.
|