trailblazer-macro 2.1.0.rc13 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
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.