trailblazer-macro 2.1.0.rc1 → 2.1.0.rc11

Sign up to get free protection for your applications and to get access to all the features.
@@ -110,6 +110,8 @@ end
110
110
  class DocsGuardInjectionTest < Minitest::Spec
111
111
  #:di-op
112
112
  class Create < Trailblazer::Operation
113
+ extend Trailblazer::Operation::Container
114
+
113
115
  step Policy::Guard( ->(options, current_user:, **) { current_user == Module } )
114
116
  end
115
117
  #:di-op end
@@ -118,7 +120,8 @@ class DocsGuardInjectionTest < Minitest::Spec
118
120
  it {
119
121
  result =
120
122
  #:di-call
121
- Create.({},
123
+ Create.(
124
+ {},
122
125
  :current_user => Module,
123
126
  "policy.default.eval" => Trailblazer::Operation::Policy::Guard.build(->(options, **) { false })
124
127
  )
@@ -6,7 +6,7 @@ class DocsMacroTest < Minitest::Spec
6
6
  def self.MyPolicy(allowed_role: "admin")
7
7
  step = ->(input, options) { options["current_user"].type == allowed_role }
8
8
 
9
- [ step, name: "my_policy.#{allowed_role}" ] # :before, :replace, etc. work, too.
9
+ {task: step, id: "my_policy.#{allowed_role}"} # :before, :replace, etc. work, too.
10
10
  end
11
11
  end
12
12
  #:simple end
@@ -28,7 +28,7 @@ class DocsMacroTest < Minitest::Spec
28
28
  end
29
29
  =end
30
30
 
31
- it { Operation::Inspect.(Create).must_equal %{[>my_policy.manager]} }
31
+ it { Trailblazer::Operation::Inspect.(Create).must_equal %{[>my_policy.manager]} }
32
32
  end
33
33
 
34
34
  # injectable option
@@ -1,113 +1,109 @@
1
1
  require "test_helper"
2
2
 
3
3
  class NestedInput < Minitest::Spec
4
- #:input-multiply
5
- class Multiplier < Trailblazer::Operation
6
- step ->(options, x:, y:, **) { options["product"] = x*y }
7
- end
8
- #:input-multiply end
9
-
10
- #:input-pi
11
- class MultiplyByPi < Trailblazer::Operation
12
- step ->(options, **) { options["pi_constant"] = 3.14159 }
13
- step Nested( Multiplier, input: ->(options, **) do
14
- { "y" => options["pi_constant"],
15
- "x" => options["x"]
16
- }
17
- end )
18
- end
19
- #:input-pi end
4
+ let(:edit) do
5
+ edit = Class.new(Trailblazer::Operation) do
6
+ step :c
20
7
 
21
- it { MultiplyByPi.("x" => 9).inspect("product").must_equal %{<Result:true [28.27431] >} }
8
+ include T.def_steps(:c)
9
+ end
10
+ end
22
11
 
23
- it do
24
- #:input-result
25
- result = MultiplyByPi.("x" => 9)
26
- result["product"] #=> [28.27431]
27
- #:input-result end
12
+ let(:update) do
13
+ edit = Class.new(Trailblazer::Operation) do
14
+ step :d
15
+ include T.def_steps(:d)
16
+ end
28
17
  end
29
- end
30
18
 
31
- class NestedInputCallable < Minitest::Spec
32
- Multiplier = NestedInput::Multiplier
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
33
26
 
34
- #:input-callable
35
- class MyInput
36
- def self.call(options, **)
37
- {
38
- "y" => options["pi_constant"],
39
- "x" => options["x"]
40
- }
27
+ include T.def_steps(:a, :b)
41
28
  end
42
- end
43
- #:input-callable end
44
29
 
45
- #:input-callable-op
46
- class MultiplyByPi < Trailblazer::Operation
47
- step ->(options, **) { options["pi_constant"] = 3.14159 }
48
- step Nested( Multiplier, input: MyInput )
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]] >}
49
35
  end
50
- #:input-callable-op end
51
-
52
- it { MultiplyByPi.("x" => 9).inspect("product").must_equal %{<Result:true [28.27431] >} }
53
- end
54
36
 
55
- class NestedWithCallableAndInputTest < Minitest::Spec
56
- Memo = Struct.new(:title, :text, :created_by)
37
+ it "Nested(Edit), with Output rewiring" do
38
+ edit = self.edit
57
39
 
58
- class Memo::Upsert < Trailblazer::Operation
59
- step Nested( :operation_class, input: :input_for_create )
40
+ create = Class.new(Trailblazer::Operation) do
41
+ step :a
42
+ step Nested( edit ), Output(:failure) => Track(:success)
43
+ step :b
60
44
 
61
- def operation_class( ctx, ** )
62
- ctx[:id] ? Update : Create
45
+ include T.def_steps(:a, :b)
63
46
  end
64
47
 
65
- # only let :title pass through.
66
- def input_for_create( ctx, ** )
67
- { title: ctx[:title] }
68
- end
48
+ # success
49
+ create.(seq: []).inspect(:seq).must_equal %{<Result:true [[:a, :c, :b]] >}
50
+ # failure in Nested
51
+ create.(seq: [], c: false).inspect(:seq).must_equal %{<Result:true [[:a, :c, :b]] >}
52
+ end
69
53
 
70
- class Create < Trailblazer::Operation
71
- step :create_memo
54
+ it "Nested(:method)" do
55
+ create = Class.new(Trailblazer::Operation) do
56
+ step :a
57
+ step Nested(:compute_edit)
58
+ step :b
72
59
 
73
- def create_memo( ctx, ** )
74
- ctx[:model] = Memo.new(ctx[:title], ctx[:text], :create)
60
+ def compute_edit(ctx, what:, **)
61
+ what
75
62
  end
63
+
64
+ include T.def_steps(:a, :b)
76
65
  end
77
66
 
78
- class Update < Trailblazer::Operation
79
- step :find_by_title
67
+ # `edit` and `update` can be called from Nested()
80
68
 
81
- def find_by_title( ctx, ** )
82
- ctx[:model] = Memo.new(ctx[:title], ctx[:text], :update)
83
- end
84
- end
85
- end
69
+ # edit/success
70
+ create.(seq: [], what: edit).inspect(:seq).must_equal %{<Result:true [[:a, :c, :b]] >}
86
71
 
87
- it "runs Create without :id" do
88
- Memo::Upsert.( title: "Yay!" ).inspect(:model).
89
- must_equal %{<Result:true [#<struct NestedWithCallableAndInputTest::Memo title=\"Yay!\", text=nil, created_by=:create>] >}
90
- end
72
+ # update/success
73
+ create.(seq: [], what: update).inspect(:seq).must_equal %{<Result:true [[:a, :d, :b]] >}
91
74
 
92
- it "runs Update without :id" do
93
- Memo::Upsert.( id: 1, title: "Yay!" ).inspect(:model).
94
- must_equal %{<Result:true [#<struct NestedWithCallableAndInputTest::Memo title=\"Yay!\", text=nil, created_by=:update>] >}
75
+
76
+ # wiring of fail:
77
+ # edit/failure
78
+ create.(seq: [], what: edit, c: false).inspect(:seq).must_equal %{<Result:false [[:a, :c]] >}
79
+ # update/failure
80
+ create.(seq: [], what: update, d: false).inspect(:seq).must_equal %{<Result:false [[:a, :d]] >}
95
81
  end
96
- end
97
82
 
98
- # builder: Nested + deviate to left if nil / skip_track if true
83
+ let(:compute_edit) {
84
+ ->(ctx, what:, **) { what }
85
+ }
86
+
87
+ it "Nested(:method), :pass_fast => :fail_fast doesn't work with standard wiring" do
88
+ skip "we need to allow adding :outputs"
99
89
 
100
- #---
101
- # automatic :name
102
- class NestedNameTest < Minitest::Spec
103
- class Create < Trailblazer::Operation
104
- class Present < Trailblazer::Operation
105
- # ...
90
+ compute_edit = self.compute_edit
91
+
92
+ pass_fast = Class.new(Trailblazer::Operation) do
93
+ step :p, pass_fast: true
94
+ include T.def_steps(:p)
106
95
  end
107
96
 
108
- step Nested( Present )
109
- # ...
110
- end
97
+ create = Class.new(Trailblazer::Operation) do
98
+ step :a
99
+ step Nested(compute_edit, auto_wire: [pass_fast]), Output(:pass_fast) => Track(:fail_fast)
100
+ step :b
101
+ include T.def_steps(:a, :b)
102
+ end
111
103
 
112
- it { Operation::Inspect.(Create).must_equal %{[>Nested(NestedNameTest::Create::Present)]} }
104
+
105
+ create.(seq: [], what: pass_fast).inspect(:seq).must_equal %{<Result:false [[:a, :c]] >}
106
+ end
113
107
  end
108
+
109
+ # TODO: test with :input/:output, tracing
@@ -11,16 +11,16 @@ class NestedRescueTest < Minitest::Spec
11
11
  step ->(options, **) { options["a"] = true }
12
12
  step Rescue {
13
13
  step ->(options, **) { options["y"] = true }
14
- success ->(options, **) { raise Y if options["raise-y"] }
14
+ pass ->(options, **) { raise Y if options["raise-y"] }
15
15
  step ->(options, **) { options["z"] = true }
16
16
  }
17
17
  step ->(options, **) { options["b"] = true }
18
- success ->(options, **) { raise A if options["raise-a"] }
18
+ pass ->(options, **) { raise A if options["raise-a"] }
19
19
  step ->(options, **) { options["c"] = true }
20
- failure ->(options, **) { options["inner-err"] = true }
20
+ fail ->(options, **) { options["inner-err"] = true }
21
21
  }
22
22
  step ->(options, **) { options["e"] = true }, id: "nested/e"
23
- failure ->(options, **) { options["outer-err"] = true }, id: "nested/failure"
23
+ fail ->(options, **) { options["outer-err"] = true }, id: "nested/failure"
24
24
  end
25
25
 
26
26
  it { Trailblazer::Operation::Inspect.(NestedInsanity).must_match /\[>Rescue\(\d+\),>nested/ } # FIXME: better introspect tests for all id-generating macros.
@@ -54,7 +54,8 @@ plain Rescue()
54
54
  step :notify
55
55
  fail :log_error
56
56
  #~methods
57
- include Test::Methods
57
+ include T.def_steps(:find_model, :update, :notify, :log_error)
58
+ include Rehash
58
59
  #~methods end
59
60
  end
60
61
 
@@ -86,7 +87,8 @@ Rescue( handler: X )
86
87
  step :notify
87
88
  fail :log_error
88
89
  #~methods
89
- include Test::Methods
90
+ include T.def_steps(:find_model, :update, :notify, :log_error)
91
+ include Rehash
90
92
  #~methods end
91
93
  end
92
94
  #:rescue end
@@ -111,7 +113,8 @@ Rescue( handler: :instance_method )
111
113
  step :notify
112
114
  fail :log_error
113
115
  #~methods
114
- include Test::Methods
116
+ include T.def_steps(:find_model, :update, :notify, :log_error)
117
+ include Rehash
115
118
  #~methods end
116
119
 
117
120
  def my_handler(exception, (ctx), *)
@@ -30,7 +30,8 @@ When raise: return {Railway.fail!}
30
30
  step :notify
31
31
  fail :log_error
32
32
  #~methods
33
- include Test::Methods
33
+ include T.def_steps(:find_model, :update, :notify, :log_error)
34
+ include Rehash
34
35
  #~methods end
35
36
  end
36
37
  #:wrap end
@@ -76,6 +77,8 @@ When raise: return {Railway.fail!}, but wire Wrap() to {fail_fast: true}
76
77
  begin
77
78
  yield # calls the wrapped steps
78
79
  rescue
80
+ puts $!
81
+ ctx[:exception] = $!.message
79
82
  [ Trailblazer::Operation::Railway.fail!, [ctx, {}] ]
80
83
  end
81
84
  end
@@ -90,7 +93,8 @@ When raise: return {Railway.fail!}, but wire Wrap() to {fail_fast: true}
90
93
  fail :log_error
91
94
 
92
95
  #~methods
93
- include Test::Methods
96
+ include T.def_steps(:find_model, :update, :notify, :log_error)
97
+ include Rehash
94
98
  #~methods end
95
99
  end
96
100
 
@@ -127,7 +131,8 @@ When raise: return {Railway.fail_fast!} and configure Wrap() to {fast_track: t
127
131
  step :notify
128
132
  fail :log_error
129
133
  #~methods
130
- include Test::Methods
134
+ include T.def_steps(:find_model, :update, :notify, :log_error)
135
+ include Rehash
131
136
  #~methods end
132
137
  end
133
138
  #:fail-fast end
@@ -176,7 +181,8 @@ When raise: return {Railway.fail!} or {Railway.pass!}
176
181
  step :notify
177
182
  fail :log_error
178
183
  #~methods
179
- include Test::Methods
184
+ include T.def_steps(:find_model, :update, :notify, :log_error)
185
+ include Rehash
180
186
  #~methods end
181
187
  end
182
188
  #:transaction end
@@ -219,7 +225,8 @@ When raise: return {Railway.fail!} or {Railway.pass!}
219
225
  step :notify
220
226
  fail :log_error
221
227
  #~methods
222
- include Test::Methods
228
+ include T.def_steps(:find_model, :update, :notify, :log_error)
229
+ include Rehash
223
230
  #~methods end
224
231
  end
225
232
  #:custom end
@@ -264,7 +271,8 @@ When raise: return {Railway.pass!} and go "successful"
264
271
  fail :log_error
265
272
 
266
273
  #~methods
267
- include Test::Methods
274
+ include T.def_steps(:find_model, :update, :notify, :log_error)
275
+ include Rehash
268
276
  #~methods end
269
277
  end
270
278
 
@@ -0,0 +1,55 @@
1
+ require "test_helper"
2
+
3
+ class IntegrationTest < Minitest::Spec
4
+ Artist = Struct.new(:name)
5
+ Song = Struct.new(:name, :artist_name)
6
+
7
+ class SongCreate < Trailblazer::Operation
8
+ step Model(Song, :new)
9
+ # step ->(options, **) { options[:model] = Song.new }
10
+ step :set_artist!
11
+ step :save!
12
+
13
+ def set_artist!(_options, model:, params:, **)
14
+ model.artist_name = params[:artist][:name]
15
+ end
16
+
17
+ def save!(_options, params:, model:, **)
18
+ model.name = params[:song][:name]
19
+ end
20
+ end
21
+
22
+ class ArtistCreate < Trailblazer::Operation
23
+ # step ->(options, **) { options[:model] = Artist.new }
24
+ step Model(Artist, :new)
25
+ step :save!
26
+
27
+ def save!(_options, params:, model:, **)
28
+ model.name = params[:artist][:name]
29
+ end
30
+ end
31
+
32
+ class SongSpecialCreate < Trailblazer::Operation
33
+ step Nested(ArtistCreate)
34
+ step Nested(SongCreate)
35
+ end
36
+
37
+ it "create Artist and Song" do
38
+ result = SongSpecialCreate.trace(
39
+ params: {
40
+ artist: {
41
+ name: "My Artist"
42
+ },
43
+ song: {
44
+ name: "My Song"
45
+ }
46
+ }
47
+ )
48
+
49
+ puts result.wtf?
50
+
51
+ # this should return song
52
+ result[:model].name.must_match "My Song"
53
+ result[:model].artist_name.must_match "My Artist"
54
+ end
55
+ end
@@ -13,15 +13,23 @@ class ModelTest < Minitest::Spec
13
13
 
14
14
  #---
15
15
  # use Model semantics, no customizations.
16
+ # class Create < Trailblazer::Operation
16
17
  class Create < Trailblazer::Operation
17
- step Model( Song, :new )
18
+ step Trailblazer::Operation::Model( Song, :new )
18
19
  end
19
20
 
20
21
  # :new new.
21
22
  it { Create.(params: {})[:model].inspect.must_equal %{#<struct ModelTest::Song id=nil, title=nil>} }
23
+ it do
24
+
25
+ result = Create.(params: {})
26
+
27
+ result[:model].inspect.must_equal %{#<struct ModelTest::Song id=nil, title=nil>}
28
+ end
22
29
 
23
- class Update < Create
24
- step Model( Song, :find ), override: true
30
+ # class Update < Create
31
+ class Update < Trailblazer::Operation
32
+ step Trailblazer::Operation::Model( Song, :find )#, override: true
25
33
  end
26
34
 
27
35
  #---
@@ -35,16 +43,18 @@ class ModelTest < Minitest::Spec
35
43
 
36
44
  #---
37
45
  # :find_by, exceptionless.
46
+ # class Find < Trailblazer::Operation
38
47
  class Find < Trailblazer::Operation
39
- step Model Song, :find_by
48
+ step Trailblazer::Operation::Model Song, :find_by
40
49
  step :process
41
50
 
42
51
  def process(options, **); options["x"] = true end
43
52
  end
44
53
 
45
54
  # :find_by, exceptionless.
55
+ # class FindByKey < Trailblazer::Operation
46
56
  class FindByKey < Trailblazer::Operation
47
- step Model( Song, :find_by, :title )
57
+ step Trailblazer::Operation::Model( Song, :find_by, :title )
48
58
  step :process
49
59
 
50
60
  def process(options, **); options["x"] = true end