trailblazer 1.1.2 → 2.0.0.beta1
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 +10 -7
- data/CHANGES.md +108 -0
- data/COMM-LICENSE +91 -0
- data/Gemfile +18 -4
- data/LICENSE.txt +7 -20
- data/README.md +55 -15
- data/Rakefile +21 -2
- data/draft-1.2.rb +7 -0
- data/lib/trailblazer.rb +17 -4
- data/lib/trailblazer/dsl.rb +47 -0
- data/lib/trailblazer/operation/auto_inject.rb +47 -0
- data/lib/trailblazer/operation/builder.rb +18 -18
- data/lib/trailblazer/operation/callback.rb +31 -38
- data/lib/trailblazer/operation/contract.rb +46 -0
- data/lib/trailblazer/operation/controller.rb +45 -27
- data/lib/trailblazer/operation/guard.rb +24 -0
- data/lib/trailblazer/operation/model.rb +41 -33
- data/lib/trailblazer/operation/nested.rb +43 -0
- data/lib/trailblazer/operation/params.rb +13 -0
- data/lib/trailblazer/operation/persist.rb +13 -0
- data/lib/trailblazer/operation/policy.rb +26 -72
- data/lib/trailblazer/operation/present.rb +19 -0
- data/lib/trailblazer/operation/procedural/contract.rb +15 -0
- data/lib/trailblazer/operation/procedural/validate.rb +22 -0
- data/lib/trailblazer/operation/pundit.rb +42 -0
- data/lib/trailblazer/operation/representer.rb +25 -92
- data/lib/trailblazer/operation/rescue.rb +23 -0
- data/lib/trailblazer/operation/resolver.rb +18 -24
- data/lib/trailblazer/operation/validate.rb +50 -0
- data/lib/trailblazer/operation/wrap.rb +37 -0
- data/lib/trailblazer/version.rb +1 -1
- data/test/{operation/controller_test.rb → controller_test.rb} +8 -4
- data/test/docs/auto_inject_test.rb +30 -0
- data/test/docs/contract_test.rb +429 -0
- data/test/docs/dry_test.rb +31 -0
- data/test/docs/guard_test.rb +143 -0
- data/test/docs/nested_test.rb +117 -0
- data/test/docs/policy_test.rb +2 -0
- data/test/docs/pundit_test.rb +109 -0
- data/test/docs/representer_test.rb +268 -0
- data/test/docs/rescue_test.rb +153 -0
- data/test/docs/wrap_test.rb +174 -0
- data/test/gemfiles/Gemfile.ruby-1.9 +3 -0
- data/test/gemfiles/Gemfile.ruby-2.0 +12 -0
- data/test/gemfiles/Gemfile.ruby-2.3 +12 -0
- data/test/module_test.rb +22 -15
- data/test/operation/builder_test.rb +66 -18
- data/test/operation/callback_test.rb +70 -0
- data/test/operation/contract_test.rb +385 -15
- data/test/operation/dsl/callback_test.rb +18 -30
- data/test/operation/dsl/contract_test.rb +209 -19
- data/test/operation/dsl/representer_test.rb +42 -15
- data/test/operation/guard_test.rb +1 -147
- data/test/operation/model_test.rb +105 -0
- data/test/operation/params_test.rb +36 -0
- data/test/operation/persist_test.rb +44 -0
- data/test/operation/pipedream_test.rb +59 -0
- data/test/operation/pipetree_test.rb +104 -0
- data/test/operation/present_test.rb +24 -0
- data/test/operation/pundit_test.rb +104 -0
- data/test/{representer_test.rb → operation/representer_test.rb} +58 -42
- data/test/operation/resolver_test.rb +34 -70
- data/test/operation_test.rb +57 -189
- data/test/test_helper.rb +23 -3
- data/trailblazer.gemspec +8 -7
- metadata +91 -59
- data/gemfiles/Gemfile.rails.lock +0 -130
- data/gemfiles/Gemfile.reform-2.0 +0 -6
- data/gemfiles/Gemfile.reform-2.1 +0 -7
- data/lib/trailblazer/autoloading.rb +0 -15
- data/lib/trailblazer/endpoint.rb +0 -31
- data/lib/trailblazer/operation.rb +0 -175
- data/lib/trailblazer/operation/collection.rb +0 -6
- data/lib/trailblazer/operation/dispatch.rb +0 -3
- data/lib/trailblazer/operation/model/dsl.rb +0 -29
- data/lib/trailblazer/operation/model/external.rb +0 -34
- data/lib/trailblazer/operation/policy/guard.rb +0 -35
- data/lib/trailblazer/operation/uploaded_file.rb +0 -77
- data/test/callback_test.rb +0 -104
- data/test/collection_test.rb +0 -57
- data/test/model_test.rb +0 -148
- data/test/operation/external_model_test.rb +0 -71
- data/test/operation/policy_test.rb +0 -97
- data/test/operation/reject_test.rb +0 -34
- data/test/rollback_test.rb +0 -47
@@ -0,0 +1,153 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class NestedRescueTest < Minitest::Spec
|
4
|
+
#---
|
5
|
+
# nested raise (i hope people won't use this but it works)
|
6
|
+
A = Class.new(RuntimeError)
|
7
|
+
Y = Class.new(RuntimeError)
|
8
|
+
|
9
|
+
class NestedInsanity < Trailblazer::Operation
|
10
|
+
step Rescue {
|
11
|
+
step ->(options) { options["a"] = true }
|
12
|
+
step Rescue {
|
13
|
+
step ->(options) { options["y"] = true }
|
14
|
+
step ->(options) { raise Y if options["raise-y"] }
|
15
|
+
step ->(options) { options["z"] = true }
|
16
|
+
}
|
17
|
+
step ->(options) { options["b"] = true }
|
18
|
+
step ->(options) { raise A if options["raise-a"] }
|
19
|
+
step ->(options) { options["c"] = true }
|
20
|
+
self.< ->(options) { options["inner-err"] = true }
|
21
|
+
}
|
22
|
+
step ->(options) { options["e"] = true }
|
23
|
+
self.< ->(options) { options["outer-err"] = true }
|
24
|
+
end
|
25
|
+
|
26
|
+
it { NestedInsanity["pipetree"].inspect.must_equal %{[>>operation.new,&Rescue:10,>:22,<NestedRescueTest::NestedInsanity:23]} }
|
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
|
+
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
|
+
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] >} }
|
30
|
+
|
31
|
+
#-
|
32
|
+
# inheritance
|
33
|
+
class UbernestedInsanity < NestedInsanity
|
34
|
+
end
|
35
|
+
|
36
|
+
it { UbernestedInsanity.({}).inspect("a", "y", "z", "b", "c", "e", "inner-err", "outer-err").must_equal %{<Result:true [true, true, true, true, true, true, nil, nil] >} }
|
37
|
+
it { UbernestedInsanity.({}, "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] >} }
|
38
|
+
end
|
39
|
+
|
40
|
+
class RescueTest < Minitest::Spec
|
41
|
+
RecordNotFound = Class.new(RuntimeError)
|
42
|
+
|
43
|
+
Song = Struct.new(:id, :title) do
|
44
|
+
def self.find(id)
|
45
|
+
raise if id == "RuntimeError!"
|
46
|
+
id.nil? ? raise(RecordNotFound) : new(id)
|
47
|
+
end
|
48
|
+
|
49
|
+
def lock!
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
#:simple
|
54
|
+
class Create < Trailblazer::Operation
|
55
|
+
class MyContract < Reform::Form
|
56
|
+
property :title
|
57
|
+
end
|
58
|
+
|
59
|
+
step Rescue {
|
60
|
+
step Model(Song, :find)
|
61
|
+
step Contract::Build( constant: MyContract )
|
62
|
+
}
|
63
|
+
step Contract::Validate()
|
64
|
+
step Persist( method: :sync )
|
65
|
+
end
|
66
|
+
#:simple end
|
67
|
+
|
68
|
+
it { Create.( id: 1, title: "Prodigal Son" )["contract.default"].model.inspect.must_equal %{#<struct RescueTest::Song id=1, title="Prodigal Son">} }
|
69
|
+
it { Create.( id: nil ).inspect("model").must_equal %{<Result:false [nil] >} }
|
70
|
+
|
71
|
+
#-
|
72
|
+
# Rescue ExceptionClass, handler: ->(*) { }
|
73
|
+
class WithExceptionNameTest < Minitest::Spec
|
74
|
+
#
|
75
|
+
class MyContract < Reform::Form
|
76
|
+
property :title
|
77
|
+
end
|
78
|
+
#:name
|
79
|
+
class Create < Trailblazer::Operation
|
80
|
+
step Rescue( RecordNotFound, KeyError, handler: :rollback! ) {
|
81
|
+
step Model( Song, :find )
|
82
|
+
step Contract::Build( constant: MyContract )
|
83
|
+
}
|
84
|
+
step Contract::Validate()
|
85
|
+
step Persist( method: :sync )
|
86
|
+
|
87
|
+
def rollback!(exception, options)
|
88
|
+
options["x"] = exception.class
|
89
|
+
end
|
90
|
+
end
|
91
|
+
#:name end
|
92
|
+
|
93
|
+
it { Create.( id: 1, title: "Prodigal Son" )["contract.default"].model.inspect.must_equal %{#<struct RescueTest::Song id=1, title="Prodigal Son">} }
|
94
|
+
it { Create.( id: 1, title: "Prodigal Son" ).inspect("x").must_equal %{<Result:true [nil] >} }
|
95
|
+
it { Create.( id: nil ).inspect("model", "x").must_equal %{<Result:false [nil, RescueTest::RecordNotFound] >} }
|
96
|
+
it { assert_raises(RuntimeError) { Create.( id: "RuntimeError!" ) } }
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
#-
|
101
|
+
# cdennl use-case
|
102
|
+
class CdennlRescueAndTransactionTest < Minitest::Spec
|
103
|
+
module Sequel
|
104
|
+
cattr_accessor :result
|
105
|
+
|
106
|
+
def self.transaction
|
107
|
+
yield.tap do |res|
|
108
|
+
self.result = res
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
#:example
|
114
|
+
class Create < Trailblazer::Operation
|
115
|
+
class MyContract < Reform::Form
|
116
|
+
property :title
|
117
|
+
end
|
118
|
+
|
119
|
+
step Rescue( RecordNotFound, handler: :rollback! ) {
|
120
|
+
step Wrap ->(*, &block) { Sequel.transaction do block.call end } {
|
121
|
+
step Model( Song, :find )
|
122
|
+
step ->(options) { options["model"].lock! } # lock the model.
|
123
|
+
step Contract::Build( constant: MyContract )
|
124
|
+
step Contract::Validate( )
|
125
|
+
step Persist( method: :sync )
|
126
|
+
}
|
127
|
+
}
|
128
|
+
failure :error! # handle all kinds of errors.
|
129
|
+
|
130
|
+
def rollback!(exception, options)
|
131
|
+
#~ex
|
132
|
+
options["x"] = exception.class
|
133
|
+
#~ex end
|
134
|
+
end
|
135
|
+
|
136
|
+
def error!(options)
|
137
|
+
#~ex
|
138
|
+
options["err"] = true
|
139
|
+
#~ex end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
#:example end
|
143
|
+
|
144
|
+
it { Create.( id: 1, title: "Pie" ).inspect("model", "x", "err").must_equal %{<Result:true [#<struct RescueTest::Song id=1, title=\"Pie\">, nil, nil] >} }
|
145
|
+
# raise exceptions in Model:
|
146
|
+
it { Create.( id: nil ).inspect("model", "x").must_equal %{<Result:false [nil, RescueTest::RecordNotFound] >} }
|
147
|
+
it { assert_raises(RuntimeError) { Create.( id: "RuntimeError!" ) } }
|
148
|
+
it do
|
149
|
+
Create.( id: 1, title: "Pie" )
|
150
|
+
Sequel.result.first.must_equal Pipetree::Flow::Right
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class WrapTest < Minitest::Spec
|
4
|
+
Song = Struct.new(:id, :title) do
|
5
|
+
def self.find(id)
|
6
|
+
id.nil? ? raise : new(id)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Create < Trailblazer::Operation
|
11
|
+
class MyContract < Reform::Form
|
12
|
+
property :title
|
13
|
+
end
|
14
|
+
|
15
|
+
step Wrap ->(options, *, &block) {
|
16
|
+
begin
|
17
|
+
block.call
|
18
|
+
rescue => exception
|
19
|
+
options["result.model.find"] = "argh! because #{exception.class}"
|
20
|
+
false
|
21
|
+
end } {
|
22
|
+
step Model( Song, :find )
|
23
|
+
step Contract::Build( constant: MyContract )
|
24
|
+
}
|
25
|
+
step Contract::Validate()
|
26
|
+
step Persist( method: :sync )
|
27
|
+
end
|
28
|
+
|
29
|
+
it { Create.( id: 1, title: "Prodigal Son" )["contract.default"].model.inspect.must_equal %{#<struct WrapTest::Song id=1, title="Prodigal Son">} }
|
30
|
+
it { Create.( id: nil ).inspect("result.model.find").must_equal %{<Result:false [\"argh! because RuntimeError\"] >} }
|
31
|
+
|
32
|
+
#-
|
33
|
+
# Wrap return
|
34
|
+
class WrapReturnTest < Minitest::Spec
|
35
|
+
class Create < Trailblazer::Operation
|
36
|
+
step Wrap ->(options, *, &block) { options["yield?"] ? block.call : false } {
|
37
|
+
step ->(options) { options["x"] = true }
|
38
|
+
step :noop!
|
39
|
+
# ...
|
40
|
+
}
|
41
|
+
|
42
|
+
def noop!(options)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it { Create.().inspect("x").must_equal %{<Result:false [nil] >} }
|
47
|
+
# returns falsey means deviate to left.
|
48
|
+
it { Create.({}, "yield?" => true).inspect("x").must_equal %{<Result:true [true] >} }
|
49
|
+
end
|
50
|
+
|
51
|
+
class WrapWithCallableTest < Minitest::Spec
|
52
|
+
class MyWrapper
|
53
|
+
extend Uber::Callable
|
54
|
+
|
55
|
+
def self.call(options, *, &block)
|
56
|
+
options["yield?"] ? yield : false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class Create < Trailblazer::Operation
|
61
|
+
step Wrap( MyWrapper ) {
|
62
|
+
step ->(options) { options["x"] = true }
|
63
|
+
# ...
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
it { Create.().inspect("x").must_equal %{<Result:false [nil] >} }
|
68
|
+
# returns falsey means deviate to left.
|
69
|
+
it { Create.({}, "yield?" => true).inspect("x").must_equal %{<Result:true [true] >} }
|
70
|
+
end
|
71
|
+
|
72
|
+
#-
|
73
|
+
# arguments for Wrap
|
74
|
+
class Update < Trailblazer::Operation
|
75
|
+
step Wrap ->(options, operation, pipe, &block) { operation["yield?"] ? block.call : false } {
|
76
|
+
step ->(options) { options["x"] = true }
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
it { Update.().inspect("x").must_equal %{<Result:false [nil] >} }
|
81
|
+
it { Update.({}, "yield?" => true).inspect("x").must_equal %{<Result:true [true] >} }
|
82
|
+
|
83
|
+
class WrapExampleProcTest < Minitest::Spec
|
84
|
+
module Sequel
|
85
|
+
def self.transaction
|
86
|
+
yield
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
#:sequel-transaction
|
91
|
+
class Create < Trailblazer::Operation
|
92
|
+
#~wrap-only
|
93
|
+
class MyContract < Reform::Form
|
94
|
+
property :title
|
95
|
+
end
|
96
|
+
|
97
|
+
#~wrap-only end
|
98
|
+
step Wrap ->(*, &block) { Sequel.transaction do block.call end } {
|
99
|
+
step Model( Song, :new )
|
100
|
+
#~wrap-only
|
101
|
+
step Contract::Build( constant: MyContract )
|
102
|
+
step Contract::Validate( )
|
103
|
+
step Persist( method: :sync )
|
104
|
+
#~wrap-only end
|
105
|
+
}
|
106
|
+
failure :error! # handle all kinds of errors.
|
107
|
+
#~wrap-only
|
108
|
+
step :notify!
|
109
|
+
|
110
|
+
def error!(options)
|
111
|
+
# handle errors after the wrap
|
112
|
+
end
|
113
|
+
|
114
|
+
def notify!(options)
|
115
|
+
# send emails, because success...
|
116
|
+
end
|
117
|
+
#~wrap-only end
|
118
|
+
end
|
119
|
+
#:sequel-transaction end
|
120
|
+
|
121
|
+
it { Create.( title: "Pie" ).inspect("model", "x", "err").must_equal %{<Result:true [#<struct WrapTest::Song id=nil, title=\"Pie\">, nil, nil] >} }
|
122
|
+
end
|
123
|
+
|
124
|
+
class WrapExampleCallableTest < Minitest::Spec
|
125
|
+
module Sequel
|
126
|
+
def self.transaction
|
127
|
+
yield
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
#:callable-t
|
132
|
+
class MyTransaction
|
133
|
+
extend Uber::Callable
|
134
|
+
|
135
|
+
def self.call(options, *)
|
136
|
+
Sequel.transaction { yield } # yield runs the nested pipe.
|
137
|
+
end
|
138
|
+
end
|
139
|
+
#:callable-t end
|
140
|
+
#:sequel-transaction-callable
|
141
|
+
class Create < Trailblazer::Operation
|
142
|
+
#~wrap-onlyy
|
143
|
+
class MyContract < Reform::Form
|
144
|
+
property :title
|
145
|
+
end
|
146
|
+
|
147
|
+
#~wrap-onlyy end
|
148
|
+
step Wrap( MyTransaction ) {
|
149
|
+
step Model( Song, :new )
|
150
|
+
#~wrap-onlyy
|
151
|
+
step Contract::Build( constant: MyContract )
|
152
|
+
step Contract::Validate( )
|
153
|
+
step Persist( method: :sync )
|
154
|
+
#~wrap-onlyy end
|
155
|
+
}
|
156
|
+
failure :error! # handle all kinds of errors.
|
157
|
+
#~wrap-onlyy
|
158
|
+
step :notify!
|
159
|
+
|
160
|
+
def error!(options)
|
161
|
+
# handle errors after the wrap
|
162
|
+
end
|
163
|
+
|
164
|
+
def notify!(options)
|
165
|
+
# send emails, because success...
|
166
|
+
end
|
167
|
+
#~wrap-onlyy end
|
168
|
+
end
|
169
|
+
#:sequel-transaction-callable end
|
170
|
+
|
171
|
+
it { Create.( title: "Pie" ).inspect("model", "x", "err").must_equal %{<Result:true [#<struct WrapTest::Song id=nil, title=\"Pie\">, nil, nil] >} }
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in trailblazer.gemspec
|
4
|
+
gemspec path: "../../"
|
5
|
+
|
6
|
+
gem "multi_json"
|
7
|
+
gem "trailblazer-operation"
|
8
|
+
gem "minitest-line"
|
9
|
+
gem "benchmark-ips"
|
10
|
+
gem "activesupport", "~> 4.2.0"
|
11
|
+
gem "reform-rails"
|
12
|
+
gem "dry-validation"
|
data/test/module_test.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
require "trailblazer/operation/module"
|
3
|
-
require "trailblazer/operation/
|
3
|
+
require "trailblazer/operation/callback"
|
4
|
+
require "trailblazer/operation/contract"
|
4
5
|
|
5
6
|
class OperationModuleTest < MiniTest::Spec
|
6
7
|
Song = Struct.new(:name, :artist)
|
7
8
|
Artist = Struct.new(:id, :full_name)
|
8
9
|
|
9
10
|
class Create < Trailblazer::Operation
|
10
|
-
include Trailblazer::Operation::
|
11
|
+
include Trailblazer::Operation::Callback
|
12
|
+
include Contract::Explicit
|
11
13
|
|
12
14
|
contract do
|
13
15
|
property :name
|
@@ -20,18 +22,21 @@ class OperationModuleTest < MiniTest::Spec
|
|
20
22
|
on_change :notify_me!
|
21
23
|
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
+
attr_reader :model
|
26
|
+
def call(params)
|
27
|
+
self["model"] = Song.new
|
25
28
|
|
26
|
-
validate(params,
|
29
|
+
validate(params, model: self["model"]) do
|
27
30
|
contract.sync
|
28
31
|
|
29
32
|
dispatch!
|
30
33
|
end
|
34
|
+
|
35
|
+
self
|
31
36
|
end
|
32
37
|
|
33
38
|
def dispatched
|
34
|
-
|
39
|
+
self["dispatched"] ||= []
|
35
40
|
end
|
36
41
|
|
37
42
|
private
|
@@ -47,6 +52,8 @@ class OperationModuleTest < MiniTest::Spec
|
|
47
52
|
contract do
|
48
53
|
property :artist, inherit: true do
|
49
54
|
property :full_name
|
55
|
+
|
56
|
+
puts definitions.inspect
|
50
57
|
end
|
51
58
|
end
|
52
59
|
|
@@ -76,18 +83,18 @@ class OperationModuleTest < MiniTest::Spec
|
|
76
83
|
it do
|
77
84
|
op = Create.({name: "Feelings", artist: {id: 1, full_name: "The Offspring"}})
|
78
85
|
|
79
|
-
op
|
80
|
-
op
|
81
|
-
op
|
82
|
-
op
|
86
|
+
op["dispatched"].must_equal [:notify_me!]
|
87
|
+
op["model"].name.must_equal "Feelings"
|
88
|
+
op["model"].artist.id.must_equal 1
|
89
|
+
op["model"].artist.full_name.must_equal nil # property not declared.
|
83
90
|
end
|
84
91
|
|
85
92
|
it do
|
86
93
|
op = Update.({name: "Feelings", artist: {id: 1, full_name: "The Offspring"}})
|
87
94
|
|
88
|
-
op
|
89
|
-
op
|
90
|
-
op
|
91
|
-
op
|
95
|
+
op["dispatched"].must_equal [:notify_me!, :notify_them!, :notify_you!]
|
96
|
+
op["model"].name.must_equal "Feelings"
|
97
|
+
op["model"].artist.id.must_equal 1
|
98
|
+
op["model"].artist.full_name.must_equal "The Offspring" # property declared via Module.
|
92
99
|
end
|
93
|
-
end
|
100
|
+
end
|
@@ -1,41 +1,89 @@
|
|
1
1
|
require "test_helper"
|
2
|
+
require "trailblazer/operation/builder"
|
2
3
|
|
3
|
-
class
|
4
|
-
|
5
|
-
|
4
|
+
class BuilderTest < MiniTest::Spec
|
5
|
+
#---
|
6
|
+
# pass proc to Builder[]
|
7
|
+
# this is the puristic way.
|
8
|
+
class A < Trailblazer::Operation
|
9
|
+
builds = ->(klass, options) do
|
10
|
+
return B if options["params"][:sub]
|
11
|
+
klass
|
12
|
+
end
|
13
|
+
|
14
|
+
self.| Builder( builds )
|
15
|
+
self.| :process
|
16
|
+
|
17
|
+
class B < A
|
6
18
|
end
|
7
19
|
|
20
|
+
def process(*); self["x"] = self.class end
|
21
|
+
end
|
22
|
+
|
23
|
+
it { A.()["x"].must_equal A }
|
24
|
+
it { A.({ sub: true })["x"].must_equal A::B }
|
25
|
+
it { A::B["builder"].must_equal nil }
|
26
|
+
|
27
|
+
#---
|
28
|
+
# use manual Builders object
|
29
|
+
MyBuilders = Uber::Builder::Builders.new
|
30
|
+
MyBuilders << ->(options) { return self::B if options["params"][:sub] }
|
31
|
+
|
32
|
+
class Create < Trailblazer::Operation
|
33
|
+
self.| Builder( MyBuilders )
|
34
|
+
self["pipetree"].> ->(input, options) { options["x"] = input.class }
|
35
|
+
end
|
36
|
+
|
37
|
+
it { Create.()["x"].must_equal Create }
|
38
|
+
|
39
|
+
#---
|
40
|
+
#- Builder inheritance
|
41
|
+
class B < A
|
42
|
+
end
|
43
|
+
|
44
|
+
it { B["pipetree"].inspect.must_equal %{[>>operation.new,>process]} }
|
45
|
+
|
46
|
+
#---
|
47
|
+
# use Builder DSL
|
48
|
+
# you don't need to include Builder in the pipetree
|
49
|
+
class ParentOperation < Trailblazer::Operation
|
8
50
|
class Sub < self
|
9
51
|
end
|
10
52
|
|
11
|
-
|
12
|
-
|
53
|
+
include Builder
|
54
|
+
builds -> (options) do
|
55
|
+
return Sub if options["params"][:sub]
|
13
56
|
end
|
57
|
+
|
58
|
+
def process(*); self["x"] = self.class end
|
59
|
+
self.| :process
|
14
60
|
end
|
15
61
|
|
16
|
-
it { ParentOperation.
|
17
|
-
it { ParentOperation.
|
18
|
-
it { ParentOperation.({}).class.must_equal ParentOperation }
|
19
|
-
it { ParentOperation.({sub: true}).class.must_equal ParentOperation::Sub }
|
62
|
+
it { ParentOperation.({})["x"].must_equal ParentOperation }
|
63
|
+
it { ParentOperation.({ sub: true })["x"].must_equal ParentOperation::Sub }
|
20
64
|
end
|
21
65
|
|
66
|
+
#---
|
67
|
+
# copying via Operation.builders
|
22
68
|
class OperationBuilderClassTest < MiniTest::Spec
|
23
69
|
class SuperOperation < Trailblazer::Operation
|
24
|
-
|
25
|
-
|
70
|
+
include Builder
|
71
|
+
|
72
|
+
builds do |options|
|
73
|
+
self::Sub if options["params"][:sub] # Sub is defined in ParentOperation.
|
26
74
|
end
|
27
75
|
end
|
28
76
|
|
29
77
|
class ParentOperation < Trailblazer::Operation
|
30
|
-
def process(params)
|
31
|
-
end
|
32
|
-
|
33
78
|
class Sub < self
|
34
79
|
end
|
35
80
|
|
36
|
-
self
|
81
|
+
self.| Builder( SuperOperation.builders )
|
82
|
+
|
83
|
+
def process(*); self["x"] = self.class end
|
84
|
+
self.| :process
|
37
85
|
end
|
38
86
|
|
39
|
-
it { ParentOperation.({}).
|
40
|
-
it { ParentOperation.({sub: true}).
|
41
|
-
end
|
87
|
+
it { ParentOperation.({})["x"].must_equal ParentOperation }
|
88
|
+
it { ParentOperation.({ sub: true })["x"].must_equal ParentOperation::Sub }
|
89
|
+
end
|