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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f650f559c9413f94e4ab3b847052cb86f8893f8e76621ca4f871378ba5459fcc
4
- data.tar.gz: 81cd6d65a460a7e5117591a7512490d031fff59fe3599830013fe846dc56104a
3
+ metadata.gz: 05d8aa98a836c3309c0d44fca95f9bad68c025b7e3358b5e2029ac3f065ad58a
4
+ data.tar.gz: 9d19baf7edee2388ae99741628729bbafb7d6eb77b09c0baebc19b7e884349f2
5
5
  SHA512:
6
- metadata.gz: '02853f1b5e504e22ab3ff29506b93b9e02db9834894b8ff6c80dcf35467e5ff6e2f549dc604ba1f18e52a549dd4e7d22d4e229fc09b52f2187bd4859b303257d'
7
- data.tar.gz: b3458af49de52c383ad41108989109174d15dbccdea39d4f6a59fde42eb01b29003883022f6e2785fd0d606be1ef90f32780e77498ddd03aa66fc929bbb3574e
6
+ metadata.gz: d5a1336a619916dc0397595a24671b8c7fcfb765fc39ccdb74a07898bf667b51a808f85cdd595916c0a15db4ffba7103cd2922545ca6d5d432d8015316581990
7
+ data.tar.gz: d9f939b6d3f3521b255de73efb4a27ce7baa7aadd4a25d7766e5adcf224a6fb0241882736306123f879b8d0821d7710f177eb233e65f39459a5afae5dea6e210
@@ -1,11 +1,12 @@
1
- sudo: false
2
1
  language: ruby
3
2
  rvm:
4
- - 2.6.2
5
- - 2.5.5
6
- - 2.4.4
7
- - 2.3.7
8
- - 2.2
9
- - 2.1
10
-
3
+ - ruby-head
4
+ - 2.7
5
+ - 2.6
6
+ - 2.5
7
+ - 2.4
11
8
  cache: bundler
9
+ jobs:
10
+ allow_failures:
11
+ - rvm: ruby-head
12
+ - rvm: 2.7
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.
@@ -1,5 +1,6 @@
1
+ require "forwardable"
1
2
  require "trailblazer/activity"
2
- require "trailblazer/activity/dsl/linear" # TODO: remove this dependency
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
- # TODO: Forwardable.def_delegators(Operation, Macro, :Model, :Wrap) would be amazing. It really sucks to extend a foreign class.
25
- # Trailblazer::Operation.singleton_class.extend Forwardable
26
- # Trailblazer::Macro.forward_macros(Trailblazer::Operation)
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
- Trailblazer::Activity::FastTrack.singleton_class.extend Forwardable
29
- Trailblazer::Macro.forward_macros(Trailblazer::Activity::FastTrack) # monkey-patching sucks.
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
- def self.Model(model_class, action = nil, find_by_key = nil)
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: "model.build", extensions: [injection]}
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?, {})
@@ -20,7 +20,7 @@ module Trailblazer
20
20
  end
21
21
  end
22
22
 
23
- Wrap(rescue_block, id: "Rescue(#{rand(100)})", &block)
23
+ Wrap(rescue_block, id: "Rescue(#{SecureRandom.hex(4)})", &block)
24
24
  # FIXME: name
25
25
  # [ step, name: "Rescue:#{block.source_location.last}" ]
26
26
  end
@@ -1,7 +1,7 @@
1
1
  module Trailblazer
2
2
  module Version
3
3
  module Macro
4
- VERSION = "2.1.0.rc13".freeze
4
+ VERSION = "2.1.3"
5
5
  end
6
6
  end
7
7
  end
@@ -1,6 +1,8 @@
1
+ require 'securerandom'
2
+
1
3
  module Trailblazer
2
4
  module Macro
3
- def self.Wrap(user_wrap, id: "Wrap/#{rand(100)}", &block)
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]
@@ -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
- #~pipeonly
9
+ #:pipeonly
10
10
  step :process
11
11
 
12
12
  def process(options, **)
13
13
  options[:x] = true
14
14
  end
15
- #~pipeonly end
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
- #~pipe-only
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
- #~pipe-only end
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
@@ -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, :[] )
@@ -16,22 +16,33 @@ class NestedInput < Minitest::Spec
16
16
  end
17
17
  end
18
18
 
19
- it "Nested(Edit), without any options" do
20
- edit = self.edit
21
-
22
- create = Class.new(Trailblazer::Operation) do
23
- step :a
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
- # this will print a DEPRECATION warning.
31
- # success
32
- create.(seq: []).inspect(:seq).must_equal %{<Result:true [[:a, :c, :b]] >}
33
- # failure in Nested
34
- create.(seq: [], c: false).inspect(:seq).must_equal %{<Result:false [[:a, :c]] >}
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
- create = Class.new(Trailblazer::Operation) do
56
- step :a
57
- step Nested(:compute_edit)
58
- step :b
59
-
60
- def compute_edit(ctx, what:, **)
61
- what
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
- include T.def_steps(:a, :b)
65
- end
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: [], what: edit).inspect(:seq).must_equal %{<Result:true [[:a, :c, :b]] >}
90
+ create.(seq: [], params: {}).inspect(:seq).must_equal %{<Result:true [[:create, :validate, :save]] >}
71
91
 
72
92
  # update/success
73
- create.(seq: [], what: update).inspect(:seq).must_equal %{<Result:true [[:a, :d, :b]] >}
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: [], what: edit, c: false).inspect(:seq).must_equal %{<Result:false [[:a, :c]] >}
98
+ create.(seq: [], params: {}, validate: false).inspect(:seq).must_equal %{<Result:false [[:create, :validate]] >}
79
99
  # update/failure
80
- create.(seq: [], what: update, d: false).inspect(:seq).must_equal %{<Result:false [[:a, :d]] >}
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) {
@@ -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\(\d+\),>nested/ } # FIXME: better introspect tests for all id-generating macros.
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] >} }
@@ -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
- begin
15
- yield # calls the wrapped steps
16
- rescue
17
- [ Trailblazer::Operation::Railway.fail!, [ctx, flow_options] ]
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
- begin
78
- yield # calls the wrapped steps
79
- rescue
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
- begin
116
- yield # calls the wrapped steps
117
- rescue
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 WrapWithTransactionTest < Minitest::Spec
149
- Memo = Module.new
143
+ class WrapWithCustomEndsTest < Minitest::Spec
144
+ Memo = Module.new
150
145
 
151
- module Sequel
152
- def self.transaction
153
- begin
154
- end_event, (ctx, flow_options) = yield
155
- true
156
- rescue
157
- false
158
- end
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
- #:transaction-handler
163
- class MyTransaction
164
- def self.call((ctx, flow_options), *, &block)
165
- result = Sequel.transaction { yield }
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
- signal = result ? Trailblazer::Operation::Railway.pass! : Trailblazer::Operation::Railway.fail!
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
- [ signal, [ctx, flow_options] ]
170
- end
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
- #:transaction-handler end
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( MyTransaction ) {
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:false [[:find_model, :update, :rehash, :log_error]] >} }
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 {Railway.fail!} or {Railway.pass!}
225
+ When raise: return {true} and go "successful"
226
+ You can return boolean true in wrap.
197
227
  =end
198
- class WrapWithCustomEndsTest < Minitest::Spec
199
- Memo = Module.new
200
- Sequel = WrapWithTransactionTest::Sequel
228
+ class WrapGoesIntoBooleanTrueFromRescueTest < Minitest::Spec
229
+ Memo = Module.new
201
230
 
202
- #:custom-handler
203
- class MyTransaction
204
- MyFailSignal = Class.new(Trailblazer::Activity::Signal)
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
- def self.call((ctx, flow_options), *, &block)
207
- result = Sequel.transaction { yield }
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
- signal = result ? Trailblazer::Operation::Railway.pass! : MyFailSignal
248
+ #~methods
249
+ include T.def_steps(:find_model, :update, :notify, :log_error)
250
+ include Rehash
251
+ #~methods end
252
+ end
210
253
 
211
- [ signal, [ctx, flow_options] ]
212
- end
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
- #:custom-handler end
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( MyTransaction ) {
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=:transaction_failed>}
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 {Railway.pass!} and go "successful"
301
+ When raise: return {nil} and go "failed"
302
+ You can return nil in wrap.
250
303
  =end
251
- class WrapGoesIntoPassFromRescueTest < Minitest::Spec
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
- begin
258
- yield # calls the wrapped steps
259
- rescue
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:true [[:find_model, :update, :rehash, :notify]] >} }
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 { Create.(params: {})[:model].inspect.must_equal %{#<struct ModelTest::Song id=nil, title=nil>} }
23
- it do
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
 
@@ -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
@@ -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 = "MIT"
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-dsl-linear", ">= 0.1.6", "< 0.2.0" # TODO: this dependency will be removed.
32
- spec.add_dependency "trailblazer-operation", ">= 0.5.2" # TODO: this dependency will be removed.
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.0.0"
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.0.rc13
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: 2019-07-24 00:00:00.000000000 Z
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.1.6
124
+ version: 0.2.7
105
125
  - - "<"
106
126
  - !ruby/object:Gem::Version
107
- version: 0.2.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.1.6
134
+ version: 0.2.7
115
135
  - - "<"
116
136
  - !ruby/object:Gem::Version
117
- version: 0.2.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.5.2
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.5.2
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.txt
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
- - MIT
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.0.0
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: 1.3.1
208
+ version: '0'
189
209
  requirements: []
190
- rubyforge_project:
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.'
@@ -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.