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
@@ -1,64 +0,0 @@
|
|
1
|
-
class Trailblazer::Operation
|
2
|
-
|
3
|
-
# false is automatically connected to End.failure.
|
4
|
-
|
5
|
-
def self.Wrap(user_wrap, id: "Wrap/#{rand(100)}", &block)
|
6
|
-
operation_class = Wrap.create_operation(block)
|
7
|
-
wrapped = Wrap::Wrapped.new(operation_class, user_wrap)
|
8
|
-
|
9
|
-
# connect `false` as an end event, when an exception stopped the wrap, for example.
|
10
|
-
|
11
|
-
{ task: wrapped, id: id, outputs: operation_class.outputs }
|
12
|
-
# TODO: Nested could have a better API and do the "merge" for us!
|
13
|
-
end
|
14
|
-
|
15
|
-
module Wrap
|
16
|
-
def self.create_operation(block)
|
17
|
-
Class.new( Nested.operation_class, &block ) # Usually resolves to Trailblazer::Operation.
|
18
|
-
end
|
19
|
-
|
20
|
-
# behaves like an operation so it plays with Nested and simply calls the operation in the user-provided block.
|
21
|
-
class Wrapped #< Trailblazer::Operation # FIXME: the inheritance is only to satisfy Nested( Wrapped.new )
|
22
|
-
include Trailblazer::Activity::Interface
|
23
|
-
|
24
|
-
def initialize(operation, user_wrap)
|
25
|
-
@operation = operation
|
26
|
-
@user_wrap = user_wrap
|
27
|
-
end
|
28
|
-
|
29
|
-
def call( (options, flow_options), **circuit_options )
|
30
|
-
block_calling_wrapped = -> {
|
31
|
-
activity = @operation.to_h[:activity]
|
32
|
-
|
33
|
-
activity.( [options, flow_options], **circuit_options )
|
34
|
-
}
|
35
|
-
|
36
|
-
# call the user's Wrap {} block in the operation.
|
37
|
-
# This will invoke block_calling_wrapped above if the user block yields.
|
38
|
-
returned = @user_wrap.( options, flow_options, **circuit_options, &block_calling_wrapped )
|
39
|
-
|
40
|
-
# returned could be
|
41
|
-
# 1. the 1..>=3 Task interface result
|
42
|
-
# 2. false
|
43
|
-
# 3. true or something else, but not the Task interface (when rescue isn't needed)
|
44
|
-
|
45
|
-
# legacy outcome.
|
46
|
-
# FIXME: we *might* return some "older version" of options here!
|
47
|
-
if returned === false
|
48
|
-
return @operation.outputs[:failure].signal, [options, flow_options]
|
49
|
-
elsif returned === true
|
50
|
-
return @operation.outputs[:success].signal, [options, flow_options]
|
51
|
-
end
|
52
|
-
|
53
|
-
returned # let's hope returned is one of activity's Ends.
|
54
|
-
end
|
55
|
-
|
56
|
-
def outputs
|
57
|
-
@operation.outputs # FIXME: we don't map false, yet
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end # Wrap
|
61
|
-
end
|
62
|
-
|
63
|
-
# (options, *) => (options, operation, bla)
|
64
|
-
# (*, params:, **) => (options, operation, bla, options)
|
data/test/docs/contract_test.rb
DELETED
@@ -1,545 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class DocsContractOverviewTest < Minitest::Spec
|
4
|
-
Song = Struct.new(:length, :title)
|
5
|
-
|
6
|
-
#:overv-reform
|
7
|
-
# app/concepts/song/create.rb
|
8
|
-
class Create < Trailblazer::Operation
|
9
|
-
#~bla
|
10
|
-
extend ClassDependencies
|
11
|
-
extend Contract::DSL
|
12
|
-
|
13
|
-
contract do
|
14
|
-
property :title
|
15
|
-
#~contractonly
|
16
|
-
property :length
|
17
|
-
|
18
|
-
validates :title, presence: true
|
19
|
-
validates :length, numericality: true
|
20
|
-
#~contractonly end
|
21
|
-
end
|
22
|
-
#~contractonly
|
23
|
-
|
24
|
-
#~bla end
|
25
|
-
step Model( Song, :new )
|
26
|
-
step Contract::Build()
|
27
|
-
step Contract::Validate()
|
28
|
-
step Contract::Persist( method: :sync )
|
29
|
-
#~contractonly end
|
30
|
-
end
|
31
|
-
#:overv-reform end
|
32
|
-
|
33
|
-
puts Trailblazer::Operation::Inspect.(Create, style: :rows)
|
34
|
-
|
35
|
-
=begin
|
36
|
-
#:overv-reform-pipe
|
37
|
-
0 ==========================&model.build
|
38
|
-
1 =======================>contract.build
|
39
|
-
2 ==============&validate.params.extract
|
40
|
-
3 ====================&contract.validate
|
41
|
-
4 =========================&persist.save
|
42
|
-
#:overv-reform-pipe end
|
43
|
-
=end
|
44
|
-
|
45
|
-
it do
|
46
|
-
assert Create["contract.default.class"] < Reform::Form
|
47
|
-
end
|
48
|
-
|
49
|
-
#- result
|
50
|
-
it do
|
51
|
-
#:result
|
52
|
-
result = Create.(params: { length: "A" })
|
53
|
-
|
54
|
-
result["result.contract.default"].success? #=> false
|
55
|
-
result["result.contract.default"].errors #=> Errors object
|
56
|
-
result["result.contract.default"].errors.messages #=> {:length=>["is not a number"]}
|
57
|
-
|
58
|
-
#:result end
|
59
|
-
result["result.contract.default"].success?.must_equal false
|
60
|
-
result["result.contract.default"].errors.messages.must_equal ({:title=>["can't be blank"], :length=>["is not a number"]})
|
61
|
-
end
|
62
|
-
|
63
|
-
it "shows 2-level tracing" do
|
64
|
-
result = Create.trace( params: { length: "A" } )
|
65
|
-
result.wtf.gsub(/0x\w+/, "").must_equal %{|-- #<Trailblazer::Activity::Start semantic=:default>
|
66
|
-
|-- model.build
|
67
|
-
|-- contract.build
|
68
|
-
|-- contract.default.validate
|
69
|
-
| |-- #<Trailblazer::Activity::Start semantic=:default>
|
70
|
-
| |-- contract.default.params_extract
|
71
|
-
| |-- contract.default.call
|
72
|
-
| `-- #<Trailblazer::Activity::End semantic=:failure>
|
73
|
-
`-- #<Trailblazer::Operation::Railway::End::Failure semantic=:failure>}
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
class DocsContractNameTest < Minitest::Spec
|
78
|
-
Song = Struct.new(:length, :title)
|
79
|
-
|
80
|
-
#:contract-name
|
81
|
-
# app/concepts/comment/update.rb
|
82
|
-
class Update < Trailblazer::Operation
|
83
|
-
#~contract
|
84
|
-
extend Contract::DSL
|
85
|
-
|
86
|
-
contract :params do
|
87
|
-
property :id
|
88
|
-
validates :id, presence: true
|
89
|
-
end
|
90
|
-
#~contract end
|
91
|
-
#~pipe
|
92
|
-
step Model( Song, :new )
|
93
|
-
step Contract::Build( name: "params" )
|
94
|
-
step Contract::Validate( name: "params" )
|
95
|
-
#~pipe end
|
96
|
-
end
|
97
|
-
#:contract-name end
|
98
|
-
end
|
99
|
-
|
100
|
-
class DocsContractReferenceTest < Minitest::Spec
|
101
|
-
MyContract = Class.new
|
102
|
-
#:contract-ref
|
103
|
-
# app/concepts/comment/update.rb
|
104
|
-
class Update < Trailblazer::Operation
|
105
|
-
#~contract
|
106
|
-
extend Contract::DSL
|
107
|
-
contract :user, MyContract
|
108
|
-
end
|
109
|
-
#:contract-ref end
|
110
|
-
end
|
111
|
-
|
112
|
-
#---
|
113
|
-
# contract MyContract
|
114
|
-
class DocsContractExplicitTest < Minitest::Spec
|
115
|
-
Song = Struct.new(:length, :title)
|
116
|
-
|
117
|
-
#:reform-inline
|
118
|
-
class MyContract < Reform::Form
|
119
|
-
property :title
|
120
|
-
property :length
|
121
|
-
|
122
|
-
validates :title, presence: true
|
123
|
-
validates :length, numericality: true
|
124
|
-
end
|
125
|
-
#:reform-inline end
|
126
|
-
|
127
|
-
#:reform-inline-op
|
128
|
-
# app/concepts/comment/create.rb
|
129
|
-
class Create < Trailblazer::Operation
|
130
|
-
extend Contract::DSL
|
131
|
-
|
132
|
-
contract MyContract
|
133
|
-
|
134
|
-
step Model( Song, :new )
|
135
|
-
step Contract::Build()
|
136
|
-
step Contract::Validate()
|
137
|
-
step Contract::Persist( method: :sync )
|
138
|
-
end
|
139
|
-
#:reform-inline-op end
|
140
|
-
end
|
141
|
-
|
142
|
-
#- Validate with manual key extraction
|
143
|
-
class DocsContractSeparateKeyTest < Minitest::Spec
|
144
|
-
Song = Struct.new(:id, :title)
|
145
|
-
#:key-extr
|
146
|
-
class Create < Trailblazer::Operation
|
147
|
-
extend ClassDependencies
|
148
|
-
extend Contract::DSL
|
149
|
-
|
150
|
-
contract do
|
151
|
-
property :title
|
152
|
-
end
|
153
|
-
|
154
|
-
def type
|
155
|
-
"evergreen" # this is how you could do polymorphic lookups.
|
156
|
-
end
|
157
|
-
|
158
|
-
step Model( Song, :new )
|
159
|
-
step Contract::Build()
|
160
|
-
step :extract_params!
|
161
|
-
step Contract::Validate( skip_extract: true )
|
162
|
-
step Contract::Persist( method: :sync )
|
163
|
-
|
164
|
-
def extract_params!(options, **)
|
165
|
-
options["contract.default.params"] = options[:params][type]
|
166
|
-
end
|
167
|
-
end
|
168
|
-
#:key-extr end
|
169
|
-
|
170
|
-
it { Create.(params: { }).inspect(:model).must_equal %{<Result:false [#<struct DocsContractSeparateKeyTest::Song id=nil, title=nil>] >} }
|
171
|
-
it { Create.(params: {"evergreen" => { title: "SVG" }}).inspect(:model).must_equal %{<Result:true [#<struct DocsContractSeparateKeyTest::Song id=nil, title="SVG">] >} }
|
172
|
-
end
|
173
|
-
|
174
|
-
#---
|
175
|
-
#- Contract::Build( constant: XXX )
|
176
|
-
class ContractConstantTest < Minitest::Spec
|
177
|
-
Song = Struct.new(:title, :length) do
|
178
|
-
def save
|
179
|
-
true
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
#:constant-contract
|
184
|
-
# app/concepts/song/contract/create.rb
|
185
|
-
module Song::Contract
|
186
|
-
class Create < Reform::Form
|
187
|
-
property :title
|
188
|
-
property :length
|
189
|
-
|
190
|
-
validates :title, length: 2..33
|
191
|
-
validates :length, numericality: true
|
192
|
-
end
|
193
|
-
end
|
194
|
-
#:constant-contract end
|
195
|
-
|
196
|
-
#:constant
|
197
|
-
class Song::Create < Trailblazer::Operation
|
198
|
-
step Model( Song, :new )
|
199
|
-
step Contract::Build( constant: Song::Contract::Create )
|
200
|
-
step Contract::Validate()
|
201
|
-
step Contract::Persist()
|
202
|
-
end
|
203
|
-
#:constant end
|
204
|
-
|
205
|
-
it { Song::Create.(params: { title: "A" }).inspect(:model).must_equal %{<Result:false [#<struct ContractConstantTest::Song title=nil, length=nil>] >} }
|
206
|
-
it { Song::Create.(params: { title: "Anthony's Song", length: 12 }).inspect(:model).must_equal %{<Result:true [#<struct ContractConstantTest::Song title="Anthony's Song", length=12>] >} }
|
207
|
-
it do
|
208
|
-
#:constant-result
|
209
|
-
result = Song::Create.(params: { title: "A" })
|
210
|
-
result.success? #=> false
|
211
|
-
result["contract.default"].errors.messages
|
212
|
-
#=> {:title=>["is too short (minimum is 2 characters)"], :length=>["is not a number"]}
|
213
|
-
#:constant-result end
|
214
|
-
|
215
|
-
#:constant-result-true
|
216
|
-
result = Song::Create.(params: { title: "Rising Force", length: 13 })
|
217
|
-
result.success? #=> true
|
218
|
-
result["model"] #=> #<Song title="Rising Force", length=13>
|
219
|
-
#:constant-result-true end
|
220
|
-
end
|
221
|
-
|
222
|
-
#---
|
223
|
-
# Song::New
|
224
|
-
#:constant-new
|
225
|
-
class Song::New < Trailblazer::Operation
|
226
|
-
step Model( Song, :new )
|
227
|
-
step Contract::Build( constant: Song::Contract::Create )
|
228
|
-
end
|
229
|
-
#:constant-new end
|
230
|
-
|
231
|
-
it { Song::New.(params: {}).inspect(:model).must_equal %{<Result:true [#<struct ContractConstantTest::Song title=nil, length=nil>] >} }
|
232
|
-
it { Song::New.(params: {})["contract.default"].model.inspect.must_equal %{#<struct ContractConstantTest::Song title=nil, length=nil>} }
|
233
|
-
it do
|
234
|
-
#:constant-new-result
|
235
|
-
result = Song::New.(params: {})
|
236
|
-
result["model"] #=> #<struct Song title=nil, length=nil>
|
237
|
-
result["contract.default"]
|
238
|
-
#=> #<Song::Contract::Create model=#<struct Song title=nil, length=nil>>
|
239
|
-
#:constant-new-result end
|
240
|
-
end
|
241
|
-
|
242
|
-
#---
|
243
|
-
#:validate-only
|
244
|
-
class Song::ValidateOnly < Trailblazer::Operation
|
245
|
-
step Model( Song, :new )
|
246
|
-
step Contract::Build( constant: Song::Contract::Create )
|
247
|
-
step Contract::Validate()
|
248
|
-
end
|
249
|
-
#:validate-only end
|
250
|
-
|
251
|
-
it { Song::ValidateOnly.(params: {}).inspect(:model).must_equal %{<Result:false [#<struct ContractConstantTest::Song title=nil, length=nil>] >} }
|
252
|
-
it do
|
253
|
-
result = Song::ValidateOnly.(params: { title: "Rising Forse", length: 13 })
|
254
|
-
result.inspect(:model).must_equal %{<Result:true [#<struct ContractConstantTest::Song title=nil, length=nil>] >}
|
255
|
-
end
|
256
|
-
|
257
|
-
it do
|
258
|
-
#:validate-only-result-false
|
259
|
-
result = Song::ValidateOnly.(params: {}) # empty params
|
260
|
-
result.success? #=> false
|
261
|
-
#:validate-only-result-false end
|
262
|
-
end
|
263
|
-
|
264
|
-
it do
|
265
|
-
#:validate-only-result
|
266
|
-
result = Song::ValidateOnly.(params: { title: "Rising Force", length: 13 })
|
267
|
-
|
268
|
-
result.success? #=> true
|
269
|
-
result["model"] #=> #<struct Song title=nil, length=nil>
|
270
|
-
result["contract.default"].title #=> "Rising Force"
|
271
|
-
#:validate-only-result end
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
#---
|
276
|
-
#- Validate( key: :song )
|
277
|
-
class DocsContractKeyTest < Minitest::Spec
|
278
|
-
Song = Class.new(ContractConstantTest::Song)
|
279
|
-
|
280
|
-
module Song::Contract
|
281
|
-
Create = ContractConstantTest::Song::Contract::Create
|
282
|
-
end
|
283
|
-
|
284
|
-
#:key
|
285
|
-
class Song::Create < Trailblazer::Operation
|
286
|
-
step Model( Song, :new )
|
287
|
-
step Contract::Build( constant: Song::Contract::Create )
|
288
|
-
step Contract::Validate( key: "song" )
|
289
|
-
step Contract::Persist( )
|
290
|
-
end
|
291
|
-
#:key end
|
292
|
-
|
293
|
-
it { Song::Create.(params: {}).inspect(:model, "result.contract.default.extract").must_equal %{<Result:false [#<struct DocsContractKeyTest::Song title=nil, length=nil>, nil] >} }
|
294
|
-
it { Song::Create.(params: {"song" => { title: "SVG", length: 13 }}).inspect(:model).must_equal %{<Result:true [#<struct DocsContractKeyTest::Song title=\"SVG\", length=13>] >} }
|
295
|
-
it do
|
296
|
-
#:key-res
|
297
|
-
result = Song::Create.(params: { "song" => { title: "Rising Force", length: 13 } })
|
298
|
-
result.success? #=> true
|
299
|
-
#:key-res end
|
300
|
-
|
301
|
-
#:key-res-false
|
302
|
-
result = Song::Create.(params: { title: "Rising Force", length: 13 })
|
303
|
-
result.success? #=> false
|
304
|
-
#:key-res-false end
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
#- Contract::Build[ constant: XXX, name: AAA ]
|
309
|
-
class ContractNamedConstantTest < Minitest::Spec
|
310
|
-
Song = Class.new(ContractConstantTest::Song)
|
311
|
-
|
312
|
-
module Song::Contract
|
313
|
-
Create = ContractConstantTest::Song::Contract::Create
|
314
|
-
end
|
315
|
-
|
316
|
-
#:constant-name
|
317
|
-
class Song::Create < Trailblazer::Operation
|
318
|
-
step Model( Song, :new )
|
319
|
-
step Contract::Build( name: "form", constant: Song::Contract::Create )
|
320
|
-
step Contract::Validate( name: "form" )
|
321
|
-
step Contract::Persist( name: "form" )
|
322
|
-
end
|
323
|
-
#:constant-name end
|
324
|
-
|
325
|
-
it { Song::Create.(params: { title: "A" }).inspect(:model).must_equal %{<Result:false [#<struct ContractNamedConstantTest::Song title=nil, length=nil>] >} }
|
326
|
-
it { Song::Create.(params: { title: "Anthony's Song", length: 13 }).inspect(:model).must_equal %{<Result:true [#<struct ContractNamedConstantTest::Song title="Anthony's Song", length=13>] >} }
|
327
|
-
|
328
|
-
it do
|
329
|
-
#:name-res
|
330
|
-
result = Song::Create.(params: { title: "A" })
|
331
|
-
result["contract.form"].errors.messages #=> {:title=>["is too short (minimum is 2 ch...
|
332
|
-
#:name-res end
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
|
-
#---
|
337
|
-
#- dependency injection
|
338
|
-
#- contract class
|
339
|
-
class ContractInjectConstantTest < Minitest::Spec
|
340
|
-
Song = Struct.new(:id, :title)
|
341
|
-
#:di-constant-contract
|
342
|
-
class MyContract < Reform::Form
|
343
|
-
property :title
|
344
|
-
validates :title, length: 2..33
|
345
|
-
end
|
346
|
-
#:di-constant-contract end
|
347
|
-
#:di-constant
|
348
|
-
class Create < Trailblazer::Operation
|
349
|
-
step Model( Song, :new )
|
350
|
-
step Contract::Build()
|
351
|
-
step Contract::Validate()
|
352
|
-
step Contract::Persist( method: :sync )
|
353
|
-
end
|
354
|
-
#:di-constant end
|
355
|
-
|
356
|
-
it do
|
357
|
-
#:di-contract-call
|
358
|
-
Create.(
|
359
|
-
params: { title: "Anthony's Song" },
|
360
|
-
"contract.default.class" => MyContract
|
361
|
-
)
|
362
|
-
#:di-contract-call end
|
363
|
-
end
|
364
|
-
it { Create.(params: { title: "A" }, "contract.default.class" => MyContract).inspect(:model).must_equal %{<Result:false [#<struct ContractInjectConstantTest::Song id=nil, title=nil>] >} }
|
365
|
-
it { Create.(params: { title: "Anthony's Song" }, "contract.default.class" => MyContract).inspect(:model).must_equal %{<Result:true [#<struct ContractInjectConstantTest::Song id=nil, title="Anthony's Song">] >} }
|
366
|
-
end
|
367
|
-
|
368
|
-
class DryValidationContractTest < Minitest::Spec
|
369
|
-
Song = Struct.new(:id, :title)
|
370
|
-
#---
|
371
|
-
# DRY-validation params validation before op,
|
372
|
-
# plus main contract.
|
373
|
-
#- result.path
|
374
|
-
#:dry-schema
|
375
|
-
require "dry/validation"
|
376
|
-
class Create < Trailblazer::Operation
|
377
|
-
extend ClassDependencies
|
378
|
-
extend Contract::DSL
|
379
|
-
|
380
|
-
# contract to verify params formally.
|
381
|
-
contract "params", (Dry::Validation.Schema do
|
382
|
-
required(:id).filled
|
383
|
-
end)
|
384
|
-
#~form
|
385
|
-
# domain validations.
|
386
|
-
contract "form" do
|
387
|
-
property :title
|
388
|
-
validates :title, length: 1..3
|
389
|
-
end
|
390
|
-
#~form end
|
391
|
-
|
392
|
-
step Contract::Validate( name: "params" )
|
393
|
-
#~form
|
394
|
-
step Model( Song, :new ) # create the op's main model.
|
395
|
-
step Contract::Build( name: "form" ) # create the Reform contract.
|
396
|
-
step Contract::Validate( name: "form" ) # validate the Reform contract.
|
397
|
-
step Contract::Persist( method: :sync, name: "form" ) # persist the contract's data via the model.
|
398
|
-
#~form end
|
399
|
-
end
|
400
|
-
#:dry-schema end
|
401
|
-
|
402
|
-
puts "@@@@@ #{Trailblazer::Operation::Inspect.(Create, style: :rows)}"
|
403
|
-
|
404
|
-
it { Create.(params: {}).inspect(:model, "result.contract.params").must_equal %{<Result:false [nil, #<Dry::Validation::Result output={} errors={:id=>[\"is missing\"]}>] >} }
|
405
|
-
it { Create.(params: { id: 1 }).inspect(:model, "result.contract.params").must_equal %{<Result:false [#<struct DryValidationContractTest::Song id=nil, title=nil>, #<Dry::Validation::Result output={:id=>1} errors={}>] >} }
|
406
|
-
# it { Create.(params: { id: 1, title: "" }).inspect(:model, "result.contract.form").must_equal %{<Result:false [#<struct DryValidationContractTest::Song id=nil, title=nil>] >} }
|
407
|
-
it { Create.(params: { id: 1, title: "" }).inspect(:model).must_equal %{<Result:false [#<struct DryValidationContractTest::Song id=nil, title=nil>] >} }
|
408
|
-
it { Create.(params: { id: 1, title: "Yo" }).inspect(:model).must_equal %{<Result:true [#<struct DryValidationContractTest::Song id=nil, title="Yo">] >} }
|
409
|
-
|
410
|
-
#:dry-schema-first
|
411
|
-
require "dry/validation"
|
412
|
-
class Delete < Trailblazer::Operation
|
413
|
-
extend ClassDependencies
|
414
|
-
extend Contract::DSL
|
415
|
-
|
416
|
-
contract "params", (Dry::Validation.Schema do
|
417
|
-
required(:id).filled
|
418
|
-
end)
|
419
|
-
|
420
|
-
step Contract::Validate( name: "params" )#, prepend: true
|
421
|
-
#~more
|
422
|
-
#~more end
|
423
|
-
end
|
424
|
-
#:dry-schema-first end
|
425
|
-
end
|
426
|
-
|
427
|
-
class DryExplicitSchemaTest < Minitest::Spec
|
428
|
-
#:dry-schema-explsch
|
429
|
-
# app/concepts/comment/contract/params.rb
|
430
|
-
require "dry/validation"
|
431
|
-
MySchema = Dry::Validation.Schema do
|
432
|
-
required(:id).filled
|
433
|
-
end
|
434
|
-
#:dry-schema-explsch end
|
435
|
-
|
436
|
-
#:dry-schema-expl
|
437
|
-
# app/concepts/comment/delete.rb
|
438
|
-
class Delete < Trailblazer::Operation
|
439
|
-
extend ClassDependencies
|
440
|
-
extend Contract::DSL
|
441
|
-
contract "params", MySchema
|
442
|
-
|
443
|
-
step Contract::Validate( name: "params" )#, prepend: true
|
444
|
-
end
|
445
|
-
#:dry-schema-expl end
|
446
|
-
end
|
447
|
-
|
448
|
-
class DocContractBuilderTest < Minitest::Spec
|
449
|
-
Song = Struct.new(:id, :title)
|
450
|
-
#---
|
451
|
-
#- builder:
|
452
|
-
#:builder-option
|
453
|
-
class Create < Trailblazer::Operation
|
454
|
-
extend ClassDependencies
|
455
|
-
extend Contract::DSL
|
456
|
-
|
457
|
-
contract do
|
458
|
-
property :title
|
459
|
-
property :current_user, virtual: true
|
460
|
-
validates :current_user, presence: true
|
461
|
-
end
|
462
|
-
|
463
|
-
step Model( Song, :new )
|
464
|
-
step Contract::Build( builder: :default_contract! )
|
465
|
-
step Contract::Validate()
|
466
|
-
step Contract::Persist( method: :sync )
|
467
|
-
|
468
|
-
def default_contract!(options, constant:, model:, **)
|
469
|
-
constant.new(model, current_user: options [:current_user])
|
470
|
-
end
|
471
|
-
end
|
472
|
-
#:builder-option end
|
473
|
-
|
474
|
-
it { Create.(params: {}).inspect(:model).must_equal %{<Result:false [#<struct DocContractBuilderTest::Song id=nil, title=nil>] >} }
|
475
|
-
it { Create.(params: { title: 1}, :current_user => Module).inspect(:model).must_equal %{<Result:true [#<struct DocContractBuilderTest::Song id=nil, title=1>] >} }
|
476
|
-
|
477
|
-
#- proc
|
478
|
-
class Update < Trailblazer::Operation
|
479
|
-
extend ClassDependencies
|
480
|
-
extend Contract::DSL
|
481
|
-
|
482
|
-
contract do
|
483
|
-
property :title
|
484
|
-
property :current_user, virtual: true
|
485
|
-
validates :current_user, presence: true
|
486
|
-
end
|
487
|
-
|
488
|
-
step Model( Song, :new )
|
489
|
-
#:builder-proc
|
490
|
-
step Contract::Build( builder: ->(options, constant:raise, model:raise, **) {
|
491
|
-
constant.new(model, current_user: options[:current_user])
|
492
|
-
})
|
493
|
-
#:builder-proc end
|
494
|
-
step Contract::Validate()
|
495
|
-
step Contract::Persist( method: :sync )
|
496
|
-
end
|
497
|
-
|
498
|
-
it { Update.(params: {}).inspect(:model).must_equal %{<Result:false [#<struct DocContractBuilderTest::Song id=nil, title=nil>] >} }
|
499
|
-
it { Update.(params: { title: 1}, :current_user => Module).inspect(:model).must_equal %{<Result:true [#<struct DocContractBuilderTest::Song id=nil, title=1>] >} }
|
500
|
-
end
|
501
|
-
|
502
|
-
class DocContractTest < Minitest::Spec
|
503
|
-
Song = Struct.new(:id, :title)
|
504
|
-
#---
|
505
|
-
# with contract block, and inheritance, the old way.
|
506
|
-
class Block < Trailblazer::Operation
|
507
|
-
extend ClassDependencies
|
508
|
-
extend Contract::DSL
|
509
|
-
contract do
|
510
|
-
property :title
|
511
|
-
end
|
512
|
-
|
513
|
-
step Model( Song, :new )
|
514
|
-
step Contract::Build() # resolves to "contract.class.default" and is resolved at runtime.
|
515
|
-
step Contract::Validate()
|
516
|
-
step Contract::Persist( method: :sync )
|
517
|
-
end
|
518
|
-
|
519
|
-
it { Block.(params: {}).inspect(:model).must_equal %{<Result:true [#<struct DocContractTest::Song id=nil, title=nil>] >} }
|
520
|
-
it { Block.(params: { id:1, title: "Fame" }).inspect(:model).must_equal %{<Result:true [#<struct DocContractTest::Song id=nil, title="Fame">] >} }
|
521
|
-
|
522
|
-
class Breach < Block
|
523
|
-
contract do
|
524
|
-
property :id
|
525
|
-
end
|
526
|
-
end
|
527
|
-
|
528
|
-
it { Breach.(params: { id:1, title: "Fame" }).inspect(:model).must_equal %{<Result:true [#<struct DocContractTest::Song id=1, title="Fame">] >} }
|
529
|
-
|
530
|
-
#-
|
531
|
-
# with constant.
|
532
|
-
class Break < Block
|
533
|
-
class MyContract < Reform::Form
|
534
|
-
property :id
|
535
|
-
end
|
536
|
-
# override the original block as if it's never been there.
|
537
|
-
contract MyContract
|
538
|
-
end
|
539
|
-
|
540
|
-
it { Break.(params: { id:1, title: "Fame" }).inspect(:model).must_equal %{<Result:true [#<struct DocContractTest::Song id=1, title=nil>] >} }
|
541
|
-
end
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
data/test/docs/dry_test.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
require "dry/container"
|
3
|
-
|
4
|
-
class DryContainerTest < Minitest::Spec
|
5
|
-
Song = Struct.new(:id, :title)
|
6
|
-
|
7
|
-
class MyContract < Reform::Form
|
8
|
-
property :title
|
9
|
-
validates :title, length: 2..33
|
10
|
-
end
|
11
|
-
|
12
|
-
my_container = Dry::Container.new
|
13
|
-
my_container.register("contract.default.class", MyContract)
|
14
|
-
# my_container.namespace("contract") do
|
15
|
-
# register("create") { Array }
|
16
|
-
# end
|
17
|
-
|
18
|
-
#---
|
19
|
-
#- dependency injection
|
20
|
-
#- with Dry-container
|
21
|
-
class Create < Trailblazer::Operation
|
22
|
-
step Model( Song, :new )
|
23
|
-
step Contract::Build()
|
24
|
-
step Contract::Validate()
|
25
|
-
step Contract::Persist( method: :sync )
|
26
|
-
end
|
27
|
-
#:key end
|
28
|
-
|
29
|
-
it { Create.({params: { title: "A" }}, my_container).inspect(:model).must_equal %{<Result:false [#<struct DryContainerTest::Song id=nil, title=nil>] >} }
|
30
|
-
it { Create.({params: { title: "Anthony's Song" }}, my_container).inspect(:model).must_equal %{<Result:true [#<struct DryContainerTest::Song id=nil, title="Anthony's Song">] >} }
|
31
|
-
end
|