trailblazer 2.1.0.beta4 → 2.1.0.beta5
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/.rubocop_todo.yml +194 -502
- data/CHANGES.md +4 -0
- data/CONTRIBUTING.md +170 -0
- data/Gemfile +4 -1
- data/README.md +183 -40
- data/Rakefile +6 -2
- data/lib/trailblazer/version.rb +1 -1
- data/lib/trailblazer.rb +3 -12
- data/test/{operation/dsl → dsl}/contract_test.rb +2 -2
- data/trailblazer.gemspec +3 -3
- metadata +17 -63
- data/lib/trailblazer/operation/contract.rb +0 -82
- data/lib/trailblazer/operation/guard.rb +0 -18
- data/lib/trailblazer/operation/model.rb +0 -65
- data/lib/trailblazer/operation/nested.rb +0 -91
- data/lib/trailblazer/operation/persist.rb +0 -14
- data/lib/trailblazer/operation/policy.rb +0 -44
- data/lib/trailblazer/operation/pundit.rb +0 -38
- data/lib/trailblazer/operation/representer.rb +0 -36
- data/lib/trailblazer/operation/rescue.rb +0 -24
- data/lib/trailblazer/operation/validate.rb +0 -74
- data/lib/trailblazer/operation/wrap.rb +0 -64
- data/test/docs/contract_test.rb +0 -545
- data/test/docs/dry_test.rb +0 -31
- data/test/docs/guard_test.rb +0 -162
- data/test/docs/macro_test.rb +0 -36
- data/test/docs/model_test.rb +0 -75
- data/test/docs/nested_test.rb +0 -300
- data/test/docs/policy_test.rb +0 -2
- data/test/docs/pundit_test.rb +0 -133
- data/test/docs/representer_test.rb +0 -268
- data/test/docs/rescue_test.rb +0 -154
- data/test/docs/wrap_test.rb +0 -219
- data/test/nested_test.rb +0 -293
- data/test/operation/contract_test.rb +0 -290
- data/test/operation/dsl/representer_test.rb +0 -169
- data/test/operation/model_test.rb +0 -54
- data/test/operation/persist_test.rb +0 -51
- data/test/operation/pundit_test.rb +0 -106
- data/test/operation/representer_test.rb +0 -254
data/test/nested_test.rb
DELETED
@@ -1,293 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
# exec_context nach Nested
|
4
|
-
|
5
|
-
class NestedTest < Minitest::Spec
|
6
|
-
#---
|
7
|
-
#- shared data
|
8
|
-
class B < Trailblazer::Operation
|
9
|
-
pass ->(options, **) { options["can.B.see.A.mutable.data?"] = options["mutable.data.from.A"] }
|
10
|
-
pass ->(options, **) { options["can.B.see.current_user?"] = options["current_user"] }
|
11
|
-
pass ->(options, **) { options["can.B.see.params?"] = options["params"] }
|
12
|
-
pass ->(options, **) { options["can.B.see.A.class.data?"] = options["A.class.data"] }
|
13
|
-
pass ->(options, **) { options["can.B.see.container.data?"] = options["some.container.data"] }
|
14
|
-
pass ->(options, **) { options["mutable.data.from.B"] = "from B!" }
|
15
|
-
end
|
16
|
-
|
17
|
-
class A < Trailblazer::Operation
|
18
|
-
extend ClassDependencies
|
19
|
-
self["A.class.data"] = "yes" # class data on A
|
20
|
-
|
21
|
-
pass ->(options, **) { options["mutable.data.from.A"] = "from A!" } # mutable data on A
|
22
|
-
step Nested( B )
|
23
|
-
pass ->(options, **) { options["can.A.see.B.mutable.data?"] = options["mutable.data.from.B"] }
|
24
|
-
end
|
25
|
-
|
26
|
-
#---
|
27
|
-
#- default behavior: share everything.
|
28
|
-
# no containers
|
29
|
-
# no runtime data
|
30
|
-
# no params
|
31
|
-
it do
|
32
|
-
result = A.("params" => {})
|
33
|
-
# everything from A visible
|
34
|
-
result["A.class.data"]. must_equal "yes"
|
35
|
-
result["mutable.data.from.A"].must_equal "from A!"
|
36
|
-
|
37
|
-
# B can see everything
|
38
|
-
result["can.B.see.A.mutable.data?"].must_equal "from A!"
|
39
|
-
result["can.B.see.current_user?"].must_be_nil
|
40
|
-
result["can.B.see.params?"].must_equal({})
|
41
|
-
result["can.B.see.A.class.data?"].must_equal "yes"
|
42
|
-
result["can.B.see.container.data?"].must_be_nil
|
43
|
-
|
44
|
-
result["can.A.see.B.mutable.data?"].must_equal "from B!"
|
45
|
-
end
|
46
|
-
|
47
|
-
#---
|
48
|
-
#- Nested::NonActivity
|
49
|
-
class AlmostB < Trailblazer::Operation
|
50
|
-
step ->(options, is_successful:raise, **) { is_successful } # {AlmostB} fails if {is_successful} isn't true.
|
51
|
-
step ->(options, **) { options["can.B.see.A.mutable.data?"] = options["mutable.data.from.A"] }
|
52
|
-
pass ->(options, **) { options["mutable.data.from.B"] = "from AlmostB!" }
|
53
|
-
end
|
54
|
-
|
55
|
-
#- Nested( ->{} )
|
56
|
-
class SomeNestedWithProc < Trailblazer::Operation
|
57
|
-
extend ClassDependencies
|
58
|
-
self["A.class.data"] = "yes" # class data on A
|
59
|
-
|
60
|
-
Decider = ->(options, use_class:raise, **) { use_class }
|
61
|
-
|
62
|
-
pass ->(options, **) { options["mutable.data.from.A"] = "from A!" } # mutable data on A
|
63
|
-
step Nested( Decider )
|
64
|
-
pass ->(options, **) { options["can.A.see.B.mutable.data?"] = options["mutable.data.from.B"] }
|
65
|
-
end
|
66
|
-
|
67
|
-
#- Nested( Callable )
|
68
|
-
class SomeNestedWithCallable < Trailblazer::Operation
|
69
|
-
extend ClassDependencies
|
70
|
-
self["A.class.data"] = "yes" # class data on A
|
71
|
-
|
72
|
-
class Decider
|
73
|
-
def self.call(options, use_class:raise, **)
|
74
|
-
use_class
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
pass ->(options, **) { options["mutable.data.from.A"] = "from A!" } # mutable data on A
|
79
|
-
step Nested( Decider )
|
80
|
-
pass ->(options, **) { options["can.A.see.B.mutable.data?"] = options["mutable.data.from.B"] }
|
81
|
-
end
|
82
|
-
|
83
|
-
#- Nested( :method )
|
84
|
-
class SomeNestedWithMethod < Trailblazer::Operation
|
85
|
-
extend ClassDependencies
|
86
|
-
self["A.class.data"] = "yes" # class data on A
|
87
|
-
|
88
|
-
def decider(options, use_class:raise, **)
|
89
|
-
use_class
|
90
|
-
end
|
91
|
-
|
92
|
-
pass ->(options, **) { options["mutable.data.from.A"] = "from A!" } # mutable data on A
|
93
|
-
step Nested( :decider )
|
94
|
-
pass ->(options, **) { options["can.A.see.B.mutable.data?"] = options["mutable.data.from.B"] }
|
95
|
-
end
|
96
|
-
|
97
|
-
|
98
|
-
#- test callable
|
99
|
-
# B with Callable, successful
|
100
|
-
it do
|
101
|
-
result = SomeNestedWithCallable.("params" => {}, use_class: B)
|
102
|
-
assert_b(result, is_successful: "whatever")
|
103
|
-
end
|
104
|
-
|
105
|
-
# AlmostB with Callable, successful
|
106
|
-
it do
|
107
|
-
result = SomeNestedWithCallable.("params" => {}, use_class: AlmostB, is_successful: true)
|
108
|
-
assert_almost_b(result, is_successful: true)
|
109
|
-
end
|
110
|
-
|
111
|
-
# AlmostB with Callable, failure
|
112
|
-
it do
|
113
|
-
result = SomeNestedWithCallable.("params" => {}, use_class: AlmostB, is_successful: false)
|
114
|
-
assert_almost_b(result, is_successful: false)
|
115
|
-
end
|
116
|
-
|
117
|
-
#- test proc
|
118
|
-
# B with proc, successful
|
119
|
-
it do
|
120
|
-
result = SomeNestedWithProc.("params" => {}, use_class: B)
|
121
|
-
assert_b(result, is_successful: "whatever")
|
122
|
-
end
|
123
|
-
|
124
|
-
# AlmostB with proc, successful
|
125
|
-
it do
|
126
|
-
result = SomeNestedWithProc.("params" => {}, use_class: AlmostB, is_successful: true)
|
127
|
-
|
128
|
-
assert_almost_b(result, is_successful: true)
|
129
|
-
end
|
130
|
-
|
131
|
-
# AlmostB with proc, failure.
|
132
|
-
it do
|
133
|
-
result = SomeNestedWithProc.("params" => {}, use_class: AlmostB, is_successful: false)
|
134
|
-
|
135
|
-
assert_almost_b(result, is_successful: false)
|
136
|
-
end
|
137
|
-
|
138
|
-
#- test :method
|
139
|
-
# B with method, successful
|
140
|
-
it do
|
141
|
-
result = SomeNestedWithMethod.("params" => {}, use_class: B)
|
142
|
-
assert_b(result, is_successful: "whatever")
|
143
|
-
end
|
144
|
-
|
145
|
-
# AlmostB with method, successful
|
146
|
-
it do
|
147
|
-
result = SomeNestedWithMethod.("params" => {}, use_class: AlmostB, is_successful: true)
|
148
|
-
|
149
|
-
assert_almost_b(result, is_successful: true)
|
150
|
-
end
|
151
|
-
|
152
|
-
# AlmostB with method, failure.
|
153
|
-
it do
|
154
|
-
result = SomeNestedWithMethod.("params" => {}, use_class: AlmostB, is_successful: false)
|
155
|
-
|
156
|
-
assert_almost_b(result, is_successful: false)
|
157
|
-
end
|
158
|
-
|
159
|
-
|
160
|
-
def assert_almost_b(result, is_successful:raise)
|
161
|
-
result.success?.must_equal is_successful # AlmostB was successful, so A is successful.
|
162
|
-
|
163
|
-
# everything from A visible
|
164
|
-
result["A.class.data"]. must_equal "yes"
|
165
|
-
result["mutable.data.from.A"].must_equal "from A!"
|
166
|
-
|
167
|
-
# AlmostB doesn't look for everything
|
168
|
-
result["can.B.see.current_user?"].must_be_nil
|
169
|
-
result["can.B.see.params?"].must_be_nil
|
170
|
-
if is_successful
|
171
|
-
result["can.B.see.A.mutable.data?"].must_equal "from A!"
|
172
|
-
result["can.B.see.A.class.data?"].must_be_nil # we don't look for it.
|
173
|
-
result["can.A.see.B.mutable.data?"].must_equal "from AlmostB!"
|
174
|
-
else
|
175
|
-
result["can.B.see.A.mutable.data?"].must_be_nil
|
176
|
-
result["can.B.see.A.class.data?"].must_be_nil
|
177
|
-
result["can.A.see.B.mutable.data?"].must_be_nil
|
178
|
-
end
|
179
|
-
result["can.B.see.container.data?"].must_be_nil
|
180
|
-
|
181
|
-
|
182
|
-
# result[:is_successful].must_equal is_successful # FIXME: this is wrong!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! key is symbol
|
183
|
-
end
|
184
|
-
|
185
|
-
def assert_b(result, is_successful:raise)
|
186
|
-
# everything from A visible
|
187
|
-
result["A.class.data"]. must_equal "yes"
|
188
|
-
result["mutable.data.from.A"].must_equal "from A!"
|
189
|
-
|
190
|
-
# B can see everything
|
191
|
-
result["can.B.see.A.mutable.data?"].must_equal "from A!"
|
192
|
-
result["can.B.see.current_user?"].must_be_nil
|
193
|
-
result["can.B.see.params?"].must_equal({})
|
194
|
-
result["can.B.see.A.class.data?"].must_equal "yes"
|
195
|
-
result["can.B.see.container.data?"].must_be_nil
|
196
|
-
|
197
|
-
result["can.A.see.B.mutable.data?"].must_equal "from B!"
|
198
|
-
|
199
|
-
result[:is_successful].must_be_nil
|
200
|
-
result.success?.must_equal true # B was successful, so A is successful.
|
201
|
-
end
|
202
|
-
|
203
|
-
|
204
|
-
#---
|
205
|
-
#- :exec_context
|
206
|
-
class Create < Trailblazer::Operation
|
207
|
-
class Edit < Trailblazer::Operation
|
208
|
-
step :c!
|
209
|
-
|
210
|
-
def c!(options, **); options[:c] = 1 end
|
211
|
-
end
|
212
|
-
|
213
|
-
step :a!
|
214
|
-
step Nested( Edit )
|
215
|
-
step :b!
|
216
|
-
|
217
|
-
def a!(options, **); options[:a] = 2 end
|
218
|
-
def b!(options, **); options[:b] = 3 end
|
219
|
-
end
|
220
|
-
|
221
|
-
it { Create.().inspect(:a, :b, :c).must_equal %{<Result:true [2, 3, 1] >} }
|
222
|
-
end
|
223
|
-
|
224
|
-
class NestedWithFastTrackTest < Minitest::Spec
|
225
|
-
module Steps
|
226
|
-
def b(options, a:, **)
|
227
|
-
options["b"] = a+1
|
228
|
-
end
|
229
|
-
|
230
|
-
def f(options, **)
|
231
|
-
options["f"] = 3
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
class Edit < Trailblazer::Operation
|
236
|
-
pass :a, pass_fast: true
|
237
|
-
|
238
|
-
def a(options, **)
|
239
|
-
options["a"] = 1
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
class Update < Trailblazer::Operation
|
244
|
-
step Nested( Edit )
|
245
|
-
step :b
|
246
|
-
fail :f
|
247
|
-
|
248
|
-
include Steps
|
249
|
-
end
|
250
|
-
|
251
|
-
# from Nested straight to End.pass_fast.
|
252
|
-
it { Update.({}).inspect("a", "b", "f").must_equal %{<Result:true [1, nil, nil] >} }
|
253
|
-
|
254
|
-
#- Nested, pass_fast: true
|
255
|
-
class Upsert < Trailblazer::Operation
|
256
|
-
step Nested( Edit ), pass_fast: true # this option is unnecessary.
|
257
|
-
step :b
|
258
|
-
fail :f
|
259
|
-
|
260
|
-
include Steps
|
261
|
-
end
|
262
|
-
|
263
|
-
# from Nested straight to End.pass_fast.
|
264
|
-
it { Upsert.({}).inspect("a", "b", "f").must_equal %{<Result:true [1, nil, nil] >} }
|
265
|
-
|
266
|
-
#- mapping
|
267
|
-
#- Nested, :pass_fast => :failure
|
268
|
-
it "attaches :pass_fast => :failure" do
|
269
|
-
op = Class.new(Trailblazer::Operation) do
|
270
|
-
step Nested( Edit ), Output(:pass_fast) => Track(:failure)
|
271
|
-
step :b
|
272
|
-
fail :f
|
273
|
-
|
274
|
-
include Steps
|
275
|
-
end
|
276
|
-
|
277
|
-
# from Nested to :failure track.
|
278
|
-
op.({}).inspect("a", "b", "c", "f").must_equal %{<Result:false [1, nil, nil, 3] >}
|
279
|
-
end
|
280
|
-
|
281
|
-
it "goes straigt to End.failure" do
|
282
|
-
op = Class.new(Trailblazer::Operation) do
|
283
|
-
step Nested( Edit ), Output(:pass_fast) => "End.failure"
|
284
|
-
step :b
|
285
|
-
fail :f
|
286
|
-
|
287
|
-
include Steps
|
288
|
-
end
|
289
|
-
|
290
|
-
# from Nested straight to End.failure, no fail step will be visited.
|
291
|
-
op.({}).inspect("a", "b", "c", "f").must_equal %{<Result:false [1, nil, nil, nil] >}
|
292
|
-
end
|
293
|
-
end
|
@@ -1,290 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
# class ContractExtractMacroTest < Minitest::Spec
|
4
|
-
# class Create < Trailblazer::Operation
|
5
|
-
# step Contract::Validate::Extract( key: "song", params_path: "x" )
|
6
|
-
# end
|
7
|
-
|
8
|
-
# it { Trailblazer::Operation::Inspect.(Create).must_equal %{[>x]} }
|
9
|
-
# it { Create.({}).inspect("x").must_equal %{<Result:false [nil] >} }
|
10
|
-
# it { Create.({ "song" => Object }).inspect("x").must_equal %{<Result:true [Object] >} }
|
11
|
-
# end
|
12
|
-
|
13
|
-
class ContractTest < Minitest::Spec
|
14
|
-
Song = Struct.new(:title)
|
15
|
-
# # generic form for testing.
|
16
|
-
# class Form
|
17
|
-
# def initialize(model, options={})
|
18
|
-
# @inspect = "#{self.class}: #{model} #{options.inspect}"
|
19
|
-
# end
|
20
|
-
|
21
|
-
# def validate
|
22
|
-
# @inspect
|
23
|
-
# end
|
24
|
-
# end
|
25
|
-
|
26
|
-
# # TODO: in all step tests.
|
27
|
-
# describe "dependency injection" do
|
28
|
-
# class Delete < Trailblazer::Operation
|
29
|
-
# include Contract::Step
|
30
|
-
# end
|
31
|
-
|
32
|
-
# class Follow < Trailblazer::Operation
|
33
|
-
# include Contract::Step
|
34
|
-
# end
|
35
|
-
|
36
|
-
# # inject contract instance via constructor.
|
37
|
-
# it { Delete.({}, "contract" => "contract/instance")["contract"].must_equal "contract/instance" }
|
38
|
-
# # inject contract class.
|
39
|
-
# it { Follow.({}, "contract.default.class" => Form)["contract"].class.must_equal Form }
|
40
|
-
# end
|
41
|
-
|
42
|
-
|
43
|
-
# # contract(model, [admin: true]).validate
|
44
|
-
# class Create < Trailblazer::Operation
|
45
|
-
# include Test::ReturnProcess
|
46
|
-
# include Contract::Explicit
|
47
|
-
|
48
|
-
# def call(options:false)
|
49
|
-
# return contract(model: Object, options: { admin: true }).validate if options
|
50
|
-
# contract(model: Object).validate
|
51
|
-
# end
|
52
|
-
# end
|
53
|
-
|
54
|
-
# # inject class, pass in model and options when constructing.
|
55
|
-
# # contract(model)
|
56
|
-
# it { Create.({}, "contract.default.class" => Form).must_equal "ContractTest::Form: Object {}" }
|
57
|
-
# # contract(model, options)
|
58
|
-
# it { Create.({ options: true }, "contract.default.class" => Form).must_equal "ContractTest::Form: Object {:admin=>true}" }
|
59
|
-
|
60
|
-
# # ::contract Form
|
61
|
-
# # contract(model).validate
|
62
|
-
# class Update < Trailblazer::Operation
|
63
|
-
# include Test::ReturnProcess
|
64
|
-
# include Contract::Explicit
|
65
|
-
|
66
|
-
# = Form
|
67
|
-
|
68
|
-
# def call(*)
|
69
|
-
# contract.validate
|
70
|
-
# end
|
71
|
-
|
72
|
-
# include Model( :Builder
|
73
|
-
# ) def model!(*)
|
74
|
-
# Object
|
75
|
-
# end
|
76
|
-
# end
|
77
|
-
|
78
|
-
# # use the class contract.
|
79
|
-
# it { Update.().must_equal "ContractTest::Form: Object {}" }
|
80
|
-
# # injected contract overrides class.
|
81
|
-
# it { Update.({}, "contract.default.class" => Injected = Class.new(Form)).must_equal "ContractTest::Injected: Object {}" }
|
82
|
-
|
83
|
-
# # passing Constant into #contract
|
84
|
-
# # contract(Object.new, { title: "Bad Feeling" }, Contract)
|
85
|
-
# class Operation < Trailblazer::Operation
|
86
|
-
# include Contract::Explicit
|
87
|
-
|
88
|
-
# class Contract < Reform::Form
|
89
|
-
# property :title, virtual: true
|
90
|
-
# end
|
91
|
-
|
92
|
-
# def process(params)
|
93
|
-
# contract(model: Object.new, options: { title: "Bad Feeling" }, contract_class: Contract)
|
94
|
-
|
95
|
-
# validate(params)
|
96
|
-
# end
|
97
|
-
# end
|
98
|
-
|
99
|
-
# # allow using #contract to inject model, options and class.
|
100
|
-
# it do
|
101
|
-
# contract = Operation.(id: 1)["contract"]
|
102
|
-
# contract.title.must_equal "Bad Feeling"
|
103
|
-
# contract.must_be_instance_of Operation::Contract
|
104
|
-
# end
|
105
|
-
|
106
|
-
# # allow using #contract before #validate.
|
107
|
-
# class Upsert < Trailblazer::Operation
|
108
|
-
# include Contract::Explicit
|
109
|
-
|
110
|
-
# contract do
|
111
|
-
# property :id
|
112
|
-
# property :title
|
113
|
-
# property :length
|
114
|
-
# end
|
115
|
-
|
116
|
-
# def process(params)
|
117
|
-
# self["model"] = Struct.new(:id, :title, :length).new
|
118
|
-
# contract.id = 1
|
119
|
-
# validate(params) { contract.length = 3 }
|
120
|
-
# end
|
121
|
-
# end
|
122
|
-
|
123
|
-
# it do
|
124
|
-
# contract = Upsert.(title: "Beethoven")["contract"]
|
125
|
-
# contract.id.must_equal 1
|
126
|
-
# contract.title.must_equal "Beethoven"
|
127
|
-
# contract.length.must_equal 3
|
128
|
-
# end
|
129
|
-
# end
|
130
|
-
|
131
|
-
#---
|
132
|
-
#- validate
|
133
|
-
class ValidateTest < Minitest::Spec
|
134
|
-
|
135
|
-
#---
|
136
|
-
# Contract::Validate[]
|
137
|
-
class Update < Trailblazer::Operation
|
138
|
-
class Form < Reform::Form
|
139
|
-
property :title
|
140
|
-
validates :title, presence: true
|
141
|
-
end
|
142
|
-
|
143
|
-
step Model( Song, :new )
|
144
|
-
step Contract::Build( constant: Form )
|
145
|
-
step Contract::Validate() # generic validate call for you.
|
146
|
-
|
147
|
-
# include Procedural::Validate
|
148
|
-
->(*) { validate(options["params"][:song]) } # <-- TODO
|
149
|
-
end
|
150
|
-
|
151
|
-
# success
|
152
|
-
it do
|
153
|
-
result = Update.(params: {title: "SVG"})
|
154
|
-
result.success?.must_equal true
|
155
|
-
result["result.contract.default"].success?.must_equal true
|
156
|
-
result["result.contract.default"].errors.messages.must_equal({})
|
157
|
-
end
|
158
|
-
|
159
|
-
# failure
|
160
|
-
it do
|
161
|
-
result = Update.(params: {title: nil})
|
162
|
-
result.success?.must_equal false
|
163
|
-
result["result.contract.default"].success?.must_equal false
|
164
|
-
result["result.contract.default"].errors.messages.must_equal({:title=>["can't be blank"]})
|
165
|
-
end
|
166
|
-
|
167
|
-
#---
|
168
|
-
# Contract::Validate[key: :song]
|
169
|
-
class Upsert < Trailblazer::Operation
|
170
|
-
class Form < Reform::Form
|
171
|
-
property :title
|
172
|
-
validates :title, presence: true
|
173
|
-
end
|
174
|
-
|
175
|
-
step Model( Song, :new ) # FIXME.
|
176
|
-
step Contract::Build( constant: Form )
|
177
|
-
step Contract::Validate( key: :song) # generic validate call for you.
|
178
|
-
# ->(*) { validate(options["params"][:song]) } # <-- TODO
|
179
|
-
step Contract::Persist( method: :sync )
|
180
|
-
end
|
181
|
-
|
182
|
-
# success
|
183
|
-
it { Upsert.(params: {song: { title: "SVG" }}).success?.must_equal true }
|
184
|
-
# failure
|
185
|
-
it { Upsert.(params: {song: { title: nil }}).success?.must_equal false }
|
186
|
-
# key not found
|
187
|
-
it { Upsert.(params: {}).success?.must_equal false }
|
188
|
-
|
189
|
-
#---
|
190
|
-
# contract.default.params gets set (TODO: change in 2.1)
|
191
|
-
it { Upsert.( params: {song: { title: "SVG" }})[:params].must_equal({:song=>{:title=>"SVG"}} ) }
|
192
|
-
it { Upsert.( params: {song: { title: "SVG" }})["contract.default.params"].must_equal({:title=>"SVG"} ) }
|
193
|
-
|
194
|
-
#---
|
195
|
-
#- inheritance
|
196
|
-
class New < Upsert
|
197
|
-
end
|
198
|
-
|
199
|
-
it { Trailblazer::Operation::Inspect.(New).must_equal %{[>model.build,>contract.build,>contract.default.validate,>persist.save]} }
|
200
|
-
|
201
|
-
#- overwriting Validate
|
202
|
-
class NewHit < Upsert
|
203
|
-
step Contract::Validate( key: :hit ), override: true
|
204
|
-
end
|
205
|
-
|
206
|
-
it { Trailblazer::Operation::Inspect.(NewHit).must_equal %{[>model.build,>contract.build,>contract.default.validate,>persist.save]} }
|
207
|
-
it { NewHit.(params: {:hit => { title: "Hooray For Me" }}).inspect(:model).must_equal %{<Result:true [#<struct ContractTest::Song title=\"Hooray For Me\">] >} }
|
208
|
-
end
|
209
|
-
|
210
|
-
# #---
|
211
|
-
# # allow using #contract to inject model and arguments.
|
212
|
-
# class OperationContractWithOptionsTest < Minitest::Spec
|
213
|
-
# # contract(model, title: "Bad Feeling")
|
214
|
-
# class Operation < Trailblazer::Operation
|
215
|
-
# include Contract::Explicit
|
216
|
-
# contract do
|
217
|
-
# property :id
|
218
|
-
# property :title, virtual: true
|
219
|
-
# end
|
220
|
-
|
221
|
-
# def process(params)
|
222
|
-
# model = Struct.new(:id).new
|
223
|
-
|
224
|
-
# contract(model: model, options: { title: "Bad Feeling" })
|
225
|
-
|
226
|
-
# validate(params)
|
227
|
-
# end
|
228
|
-
# end
|
229
|
-
|
230
|
-
# it do
|
231
|
-
# op = Operation.(id: 1)
|
232
|
-
# op["contract"].id.must_equal 1
|
233
|
-
# op["contract"].title.must_equal "Bad Feeling"
|
234
|
-
# end
|
235
|
-
|
236
|
-
# # contract({ song: song, album: album }, title: "Medicine Balls")
|
237
|
-
# class CompositionOperation < Trailblazer::Operation
|
238
|
-
# include Contract::Explicit
|
239
|
-
# contract do
|
240
|
-
# include Reform::Form::Composition
|
241
|
-
# property :song_id, on: :song
|
242
|
-
# property :album_name, on: :album
|
243
|
-
# property :title, virtual: true
|
244
|
-
# end
|
245
|
-
|
246
|
-
# def process(params)
|
247
|
-
# song = Struct.new(:song_id).new(1)
|
248
|
-
# album = Struct.new(:album_name).new("Forever Malcom Young")
|
249
|
-
|
250
|
-
# contract(model: { song: song, album: album }, options: { title: "Medicine Balls" })
|
251
|
-
|
252
|
-
# validate(params)
|
253
|
-
# end
|
254
|
-
# end
|
255
|
-
|
256
|
-
# it do
|
257
|
-
# contract = CompositionOperation.({})["contract"]
|
258
|
-
# contract.song_id.must_equal 1
|
259
|
-
# contract.album_name.must_equal "Forever Malcom Young"
|
260
|
-
# contract.title.must_equal "Medicine Balls"
|
261
|
-
# end
|
262
|
-
|
263
|
-
# # validate(params, { song: song, album: album }, title: "Medicine Balls")
|
264
|
-
# class CompositionValidateOperation < Trailblazer::Operation
|
265
|
-
# include Contract::Explicit
|
266
|
-
# contract do
|
267
|
-
# include Reform::Form::Composition
|
268
|
-
# property :song_id, on: :song
|
269
|
-
# property :album_name, on: :album
|
270
|
-
# property :title, virtual: true
|
271
|
-
# end
|
272
|
-
|
273
|
-
# def process(params)
|
274
|
-
# song = Struct.new(:song_id).new(1)
|
275
|
-
# album = Struct.new(:album_name).new("Forever Malcom Young")
|
276
|
-
|
277
|
-
# validate(params, model: { song: song, album: album }, options: { title: "Medicine Balls" })
|
278
|
-
# end
|
279
|
-
# end
|
280
|
-
|
281
|
-
# it do
|
282
|
-
# contract = CompositionValidateOperation.({})["contract"]
|
283
|
-
# contract.song_id.must_equal 1
|
284
|
-
# contract.album_name.must_equal "Forever Malcom Young"
|
285
|
-
# contract.title.must_equal "Medicine Balls"
|
286
|
-
# end
|
287
|
-
end
|
288
|
-
|
289
|
-
# TODO: full stack test with validate, process, save, etc.
|
290
|
-
# with model!
|