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/docs/guard_test.rb
DELETED
@@ -1,162 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
#--
|
4
|
-
# with proc
|
5
|
-
class DocsGuardProcTest < Minitest::Spec
|
6
|
-
#:proc
|
7
|
-
class Create < Trailblazer::Operation
|
8
|
-
step Policy::Guard( ->(options, pass:, **) { pass } )
|
9
|
-
#~pipeonly
|
10
|
-
step :process
|
11
|
-
|
12
|
-
def process(options, **)
|
13
|
-
options["x"] = true
|
14
|
-
end
|
15
|
-
#~pipeonly end
|
16
|
-
end
|
17
|
-
#:proc end
|
18
|
-
|
19
|
-
it { Create.(pass: false)["x"].must_be_nil }
|
20
|
-
it { Create.(pass: true)["x"].must_equal true }
|
21
|
-
|
22
|
-
#- result object, guard
|
23
|
-
it { Create.(pass: true)["result.policy.default"].success?.must_equal true }
|
24
|
-
it { Create.(pass: false)["result.policy.default"].success?.must_equal false }
|
25
|
-
|
26
|
-
#---
|
27
|
-
#- Guard inheritance
|
28
|
-
class New < Create
|
29
|
-
step Policy::Guard( ->(options, current_user:, **) { current_user } ), override: true
|
30
|
-
end
|
31
|
-
|
32
|
-
it { Trailblazer::Operation::Inspect.(New).must_equal %{[>policy.default.eval,>process]} }
|
33
|
-
end
|
34
|
-
|
35
|
-
#---
|
36
|
-
# with Callable
|
37
|
-
class DocsGuardTest < Minitest::Spec
|
38
|
-
#:callable
|
39
|
-
class MyGuard
|
40
|
-
include Uber::Callable
|
41
|
-
|
42
|
-
def call(options, pass:, **)
|
43
|
-
pass
|
44
|
-
end
|
45
|
-
end
|
46
|
-
#:callable end
|
47
|
-
|
48
|
-
#:callable-op
|
49
|
-
class Create < Trailblazer::Operation
|
50
|
-
step Policy::Guard( MyGuard.new )
|
51
|
-
#~pipe-only
|
52
|
-
step :process
|
53
|
-
|
54
|
-
def process(options, **)
|
55
|
-
options[:x] = true
|
56
|
-
end
|
57
|
-
#~pipe-only end
|
58
|
-
end
|
59
|
-
#:callable-op end
|
60
|
-
|
61
|
-
it { Create.(pass: false)[:x].must_be_nil }
|
62
|
-
it { Create.(pass: true)[:x].must_equal true }
|
63
|
-
end
|
64
|
-
|
65
|
-
#---
|
66
|
-
# with method
|
67
|
-
class DocsGuardMethodTest < Minitest::Spec
|
68
|
-
#:method
|
69
|
-
class Create < Trailblazer::Operation
|
70
|
-
step Policy::Guard( :pass? )
|
71
|
-
|
72
|
-
def pass?(options, pass:, **)
|
73
|
-
pass
|
74
|
-
end
|
75
|
-
#~pipe-onlyy
|
76
|
-
step :process
|
77
|
-
|
78
|
-
def process(options, **)
|
79
|
-
options["x"] = true
|
80
|
-
end
|
81
|
-
#~pipe-onlyy end
|
82
|
-
end
|
83
|
-
#:method end
|
84
|
-
|
85
|
-
it { Create.(pass: false).inspect("x").must_equal %{<Result:false [nil] >} }
|
86
|
-
it { Create.(pass: true).inspect("x").must_equal %{<Result:true [true] >} }
|
87
|
-
end
|
88
|
-
|
89
|
-
#---
|
90
|
-
# with name:
|
91
|
-
class DocsGuardNamedTest < Minitest::Spec
|
92
|
-
#:name
|
93
|
-
class Create < Trailblazer::Operation
|
94
|
-
step Policy::Guard( ->(options, current_user:, **) { current_user }, name: :user )
|
95
|
-
# ...
|
96
|
-
end
|
97
|
-
#:name end
|
98
|
-
|
99
|
-
it { Create.(:current_user => nil )["result.policy.user"].success?.must_equal false }
|
100
|
-
it { Create.(:current_user => Module)["result.policy.user"].success?.must_equal true }
|
101
|
-
|
102
|
-
it {
|
103
|
-
#:name-result
|
104
|
-
result = Create.(:current_user => true)
|
105
|
-
result["result.policy.user"].success? #=> true
|
106
|
-
#:name-result end
|
107
|
-
}
|
108
|
-
end
|
109
|
-
|
110
|
-
#---
|
111
|
-
# dependency injection
|
112
|
-
class DocsGuardInjectionTest < Minitest::Spec
|
113
|
-
#:di-op
|
114
|
-
class Create < Trailblazer::Operation
|
115
|
-
step Policy::Guard( ->(options, current_user:, **) { current_user == Module } )
|
116
|
-
end
|
117
|
-
#:di-op end
|
118
|
-
|
119
|
-
it { Create.(:current_user => Module).inspect("").must_equal %{<Result:true [nil] >} }
|
120
|
-
it {
|
121
|
-
result =
|
122
|
-
#:di-call
|
123
|
-
Create.({},
|
124
|
-
:current_user => Module,
|
125
|
-
"policy.default.eval" => Trailblazer::Operation::Policy::Guard.build(->(options, **) { false })
|
126
|
-
)
|
127
|
-
#:di-call end
|
128
|
-
result.inspect("").must_equal %{<Result:false [nil] >} }
|
129
|
-
end
|
130
|
-
|
131
|
-
#---
|
132
|
-
# missing current_user throws exception
|
133
|
-
class DocsGuardMissingKeywordTest < Minitest::Spec
|
134
|
-
class Create < Trailblazer::Operation
|
135
|
-
step Policy::Guard( ->(options, current_user:, **) { current_user == Module } )
|
136
|
-
end
|
137
|
-
|
138
|
-
it { assert_raises(ArgumentError) { Create.() } }
|
139
|
-
it { Create.(:current_user => Module).success?.must_equal true }
|
140
|
-
end
|
141
|
-
|
142
|
-
#---
|
143
|
-
# before:
|
144
|
-
class DocsGuardPositionTest < Minitest::Spec
|
145
|
-
#:before
|
146
|
-
class Create < Trailblazer::Operation
|
147
|
-
step :model!
|
148
|
-
step Policy::Guard( :authorize! ),
|
149
|
-
before: :model!
|
150
|
-
end
|
151
|
-
#:before end
|
152
|
-
|
153
|
-
it { Trailblazer::Operation::Inspect.(Create).must_equal %{[>policy.default.eval,>model!]} }
|
154
|
-
it do
|
155
|
-
#:before-pipe
|
156
|
-
Trailblazer::Operation::Inspect.(Create, style: :rows) #=>
|
157
|
-
# 0 ========================>operation.new
|
158
|
-
# 1 ==================>policy.default.eval
|
159
|
-
# 2 ===============================>model!
|
160
|
-
#:before-pipe end
|
161
|
-
end
|
162
|
-
end
|
data/test/docs/macro_test.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class DocsMacroTest < Minitest::Spec
|
4
|
-
#:simple
|
5
|
-
module Macro
|
6
|
-
def self.MyPolicy(allowed_role: "admin")
|
7
|
-
step = ->(input, options) { options["current_user"].type == allowed_role }
|
8
|
-
|
9
|
-
[ step, name: "my_policy.#{allowed_role}" ] # :before, :replace, etc. work, too.
|
10
|
-
end
|
11
|
-
end
|
12
|
-
#:simple end
|
13
|
-
|
14
|
-
#:simple-op
|
15
|
-
class Create < Trailblazer::Operation
|
16
|
-
step Macro::MyPolicy( allowed_role: "manager" )
|
17
|
-
# ..
|
18
|
-
end
|
19
|
-
#:simple-op end
|
20
|
-
|
21
|
-
=begin
|
22
|
-
it do
|
23
|
-
#:simple-pipe
|
24
|
-
puts Create["pipetree"].inspect(style: :rows) #=>
|
25
|
-
0 ========================>operation.new
|
26
|
-
1 ====================>my_policy.manager
|
27
|
-
#:simple-pipe end
|
28
|
-
end
|
29
|
-
=end
|
30
|
-
|
31
|
-
it { Operation::Inspect.(Create).must_equal %{[>my_policy.manager]} }
|
32
|
-
end
|
33
|
-
|
34
|
-
# injectable option
|
35
|
-
# nested pipe
|
36
|
-
# using macros in macros
|
data/test/docs/model_test.rb
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class DocsModelTest < Minitest::Spec
|
4
|
-
Song = Struct.new(:id, :title) do
|
5
|
-
def self.find_by(id:nil)
|
6
|
-
id.nil? ? nil : new(id)
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.[](id)
|
10
|
-
id.nil? ? nil : new(id+99)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
#:op
|
15
|
-
class Create < Trailblazer::Operation
|
16
|
-
step Model( Song, :new )
|
17
|
-
# ..
|
18
|
-
end
|
19
|
-
#:op end
|
20
|
-
|
21
|
-
it do
|
22
|
-
#:create
|
23
|
-
result = Create.(params: {})
|
24
|
-
result[:model] #=> #<struct Song id=nil, title=nil>
|
25
|
-
#:create end
|
26
|
-
|
27
|
-
result[:model].inspect.must_equal %{#<struct DocsModelTest::Song id=nil, title=nil>}
|
28
|
-
end
|
29
|
-
|
30
|
-
#:update
|
31
|
-
class Update < Trailblazer::Operation
|
32
|
-
step Model( Song, :find_by )
|
33
|
-
# ..
|
34
|
-
end
|
35
|
-
#:update end
|
36
|
-
|
37
|
-
it do
|
38
|
-
#:update-ok
|
39
|
-
result = Update.(params: { id: 1 })
|
40
|
-
result[:model] #=> #<struct Song id=1, title="Roxanne">
|
41
|
-
#:update-ok end
|
42
|
-
|
43
|
-
result[:model].inspect.must_equal %{#<struct DocsModelTest::Song id=1, title=nil>}
|
44
|
-
end
|
45
|
-
|
46
|
-
it do
|
47
|
-
#:update-fail
|
48
|
-
result = Update.(params: {})
|
49
|
-
result[:model] #=> nil
|
50
|
-
result.success? #=> false
|
51
|
-
#:update-fail end
|
52
|
-
|
53
|
-
result[:model].must_be_nil
|
54
|
-
result.success?.must_equal false
|
55
|
-
end
|
56
|
-
|
57
|
-
#:show
|
58
|
-
class Show < Trailblazer::Operation
|
59
|
-
step Model( Song, :[] )
|
60
|
-
# ..
|
61
|
-
end
|
62
|
-
#:show end
|
63
|
-
|
64
|
-
it do
|
65
|
-
result = Show.(params: { id: 1 })
|
66
|
-
|
67
|
-
#:show-ok
|
68
|
-
result = Show.(params: { id: 1 })
|
69
|
-
result[:model] #=> #<struct Song id=1, title="Roxanne">
|
70
|
-
#:show-ok end
|
71
|
-
|
72
|
-
result.success?.must_equal true
|
73
|
-
result[:model].inspect.must_equal %{#<struct DocsModelTest::Song id=100, title=nil>}
|
74
|
-
end
|
75
|
-
end
|
data/test/docs/nested_test.rb
DELETED
@@ -1,300 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class DocsNestedOperationTest < Minitest::Spec
|
4
|
-
Song = Struct.new(:id, :title) do
|
5
|
-
def self.find(id)
|
6
|
-
return new(1, "Bristol") if id == 1
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
#---
|
11
|
-
#- nested operations
|
12
|
-
#:edit
|
13
|
-
class Edit < Trailblazer::Operation
|
14
|
-
extend ClassDependencies
|
15
|
-
extend Contract::DSL
|
16
|
-
|
17
|
-
contract do
|
18
|
-
property :title
|
19
|
-
end
|
20
|
-
|
21
|
-
step Model( Song, :find )
|
22
|
-
step Contract::Build()
|
23
|
-
end
|
24
|
-
#:edit end
|
25
|
-
|
26
|
-
# step Nested( Edit ) #, "policy.default" => self["policy.create"]
|
27
|
-
#:update
|
28
|
-
class Update < Trailblazer::Operation
|
29
|
-
step Nested( Edit )
|
30
|
-
# step ->(options, **) { puts options.keys.inspect }
|
31
|
-
step Contract::Validate()
|
32
|
-
|
33
|
-
step Contract::Persist( method: :sync )
|
34
|
-
end
|
35
|
-
#:update end
|
36
|
-
|
37
|
-
# puts Update["pipetree"].inspect(style: :rows)
|
38
|
-
|
39
|
-
#-
|
40
|
-
# Edit allows grabbing model and contract
|
41
|
-
it do
|
42
|
-
#:edit-call
|
43
|
-
result = Edit.(params: {id: 1})
|
44
|
-
|
45
|
-
result[:model] #=> #<Song id=1, title=\"Bristol\">
|
46
|
-
result["contract.default"] #=> #<Reform::Form ..>
|
47
|
-
#:edit-call end
|
48
|
-
result.inspect(:model).must_equal %{<Result:true [#<struct DocsNestedOperationTest::Song id=1, title=\"Bristol\">] >}
|
49
|
-
result["contract.default"].model.must_equal result[:model]
|
50
|
-
end
|
51
|
-
|
52
|
-
#- test Edit circuit-level.
|
53
|
-
it do
|
54
|
-
signal, (result, _) = Edit.__call__( [Trailblazer::Context( params: {id: 1} ), {}] )
|
55
|
-
result[:model].inspect.must_equal %{#<struct DocsNestedOperationTest::Song id=1, title=\"Bristol\">}
|
56
|
-
end
|
57
|
-
|
58
|
-
#-
|
59
|
-
# Update also allows grabbing Edit/model and Edit/contract
|
60
|
-
it do
|
61
|
-
#:update-call
|
62
|
-
result = Update.(params: {id: 1, title: "Call It A Night"})
|
63
|
-
|
64
|
-
result[:model] #=> #<Song id=1 , title=\"Call It A Night\">
|
65
|
-
result["contract.default"] #=> #<Reform::Form ..>
|
66
|
-
#:update-call end
|
67
|
-
result.inspect(:model).must_equal %{<Result:true [#<struct DocsNestedOperationTest::Song id=1, title=\"Call It A Night\">] >}
|
68
|
-
result["contract.default"].model.must_equal result[:model]
|
69
|
-
end
|
70
|
-
|
71
|
-
#-
|
72
|
-
# Edit is successful.
|
73
|
-
it do
|
74
|
-
result = Update.(params: { id: 1, title: "Miami" }, current_user: Module)
|
75
|
-
result.inspect(:model).must_equal %{<Result:true [#<struct DocsNestedOperationTest::Song id=1, title="Miami">] >}
|
76
|
-
end
|
77
|
-
|
78
|
-
# Edit fails
|
79
|
-
it do
|
80
|
-
Update.(params: {id: 2}).inspect(:model).must_equal %{<Result:false [nil] >}
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
class NestedInput < Minitest::Spec
|
85
|
-
#:input-multiply
|
86
|
-
class Multiplier < Trailblazer::Operation
|
87
|
-
step ->(options, x:, y:, **) { options["product"] = x*y }
|
88
|
-
end
|
89
|
-
#:input-multiply end
|
90
|
-
|
91
|
-
#:input-pi
|
92
|
-
class MultiplyByPi < Trailblazer::Operation
|
93
|
-
step ->(options, **) { options["pi_constant"] = 3.14159 }
|
94
|
-
step Nested( Multiplier, input: ->(options, **) do
|
95
|
-
{ "y" => options["pi_constant"],
|
96
|
-
"x" => options["x"]
|
97
|
-
}
|
98
|
-
end )
|
99
|
-
end
|
100
|
-
#:input-pi end
|
101
|
-
|
102
|
-
it { MultiplyByPi.("x" => 9).inspect("product").must_equal %{<Result:true [28.27431] >} }
|
103
|
-
|
104
|
-
it do
|
105
|
-
#:input-result
|
106
|
-
result = MultiplyByPi.("x" => 9)
|
107
|
-
result["product"] #=> [28.27431]
|
108
|
-
#:input-result end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
class NestedInputCallable < Minitest::Spec
|
113
|
-
Multiplier = NestedInput::Multiplier
|
114
|
-
|
115
|
-
#:input-callable
|
116
|
-
class MyInput
|
117
|
-
def self.call(options, **)
|
118
|
-
{
|
119
|
-
"y" => options["pi_constant"],
|
120
|
-
"x" => options["x"]
|
121
|
-
}
|
122
|
-
end
|
123
|
-
end
|
124
|
-
#:input-callable end
|
125
|
-
|
126
|
-
#:input-callable-op
|
127
|
-
class MultiplyByPi < Trailblazer::Operation
|
128
|
-
step ->(options, **) { options["pi_constant"] = 3.14159 }
|
129
|
-
step Nested( Multiplier, input: MyInput )
|
130
|
-
end
|
131
|
-
#:input-callable-op end
|
132
|
-
|
133
|
-
it { MultiplyByPi.("x" => 9).inspect("product").must_equal %{<Result:true [28.27431] >} }
|
134
|
-
end
|
135
|
-
|
136
|
-
#---
|
137
|
-
#- Nested( .., output: )
|
138
|
-
class NestedOutput < Minitest::Spec
|
139
|
-
Edit = DocsNestedOperationTest::Edit
|
140
|
-
|
141
|
-
#:output
|
142
|
-
class Update < Trailblazer::Operation
|
143
|
-
step Nested( Edit, output: ->( ctx, ** ) do
|
144
|
-
{
|
145
|
-
"contract.my" => ctx["contract.default"],
|
146
|
-
model: ctx[:model]
|
147
|
-
}
|
148
|
-
end )
|
149
|
-
step Contract::Validate( name: "my" )
|
150
|
-
step Contract::Persist( method: :sync, name: "my" )
|
151
|
-
end
|
152
|
-
#:output end
|
153
|
-
|
154
|
-
it { Update.( params: {id: 1, title: "Call It A Night"} ).inspect(:model, "contract.default").
|
155
|
-
must_equal %{<Result:true [#<struct DocsNestedOperationTest::Song id=1, title=\"Call It A Night\">, nil] >} }
|
156
|
-
|
157
|
-
it do
|
158
|
-
result = Update.( params: {id: 1, title: "Call It A Night"} )
|
159
|
-
|
160
|
-
result[:model] #=> #<Song id=1 , title=\"Call It A Night\">
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
#---
|
165
|
-
# Nested( ->{} )
|
166
|
-
class NestedWithCallableTest < Minitest::Spec
|
167
|
-
Song = Struct.new(:id, :title)
|
168
|
-
|
169
|
-
module Song::Contract
|
170
|
-
class Create < Reform::Form
|
171
|
-
property :title
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
User = Struct.new(:is_admin) do
|
176
|
-
def admin?
|
177
|
-
!! is_admin
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
class Create < Trailblazer::Operation
|
182
|
-
step Nested( ->(options, current_user:nil, **) { current_user.admin? ? Admin : NeedsModeration })
|
183
|
-
|
184
|
-
class NeedsModeration < Trailblazer::Operation
|
185
|
-
step Model( Song, :new )
|
186
|
-
step Contract::Build( constant: Song::Contract::Create )
|
187
|
-
step Contract::Validate()
|
188
|
-
step :notify_moderator!
|
189
|
-
|
190
|
-
def notify_moderator!(options, **)
|
191
|
-
#~noti
|
192
|
-
options["x"] = true
|
193
|
-
#~noti end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
class Admin < Trailblazer::Operation # TODO: test if current_user is passed in.
|
198
|
-
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
let (:admin) { User.new(true) }
|
203
|
-
let (:anonymous) { User.new(false) }
|
204
|
-
|
205
|
-
it { Create.(params: {}, current_user: anonymous).inspect("x").must_equal %{<Result:true [true] >} }
|
206
|
-
it { Create.(params: {}, current_user: admin) .inspect("x").must_equal %{<Result:true [nil] >} }
|
207
|
-
|
208
|
-
#---
|
209
|
-
#:method
|
210
|
-
class Update < Trailblazer::Operation
|
211
|
-
step Nested( :build! )
|
212
|
-
|
213
|
-
def build!(options, current_user:nil, **)
|
214
|
-
current_user.admin? ? Create::Admin : Create::NeedsModeration
|
215
|
-
end
|
216
|
-
end
|
217
|
-
#:method end
|
218
|
-
|
219
|
-
it { Update.(params: {}, current_user: anonymous).inspect("x").must_equal %{<Result:true [true] >} }
|
220
|
-
it { Update.(params: {}, current_user: admin) .inspect("x").must_equal %{<Result:true [nil] >} }
|
221
|
-
|
222
|
-
#---
|
223
|
-
#:callable-builder
|
224
|
-
class MyBuilder
|
225
|
-
def self.call(options, current_user:nil, **)
|
226
|
-
current_user.admin? ? Create::Admin : Create::NeedsModeration
|
227
|
-
end
|
228
|
-
end
|
229
|
-
#:callable-builder end
|
230
|
-
|
231
|
-
#:callable
|
232
|
-
class Delete < Trailblazer::Operation
|
233
|
-
step Nested( MyBuilder )
|
234
|
-
# ..
|
235
|
-
end
|
236
|
-
#:callable end
|
237
|
-
|
238
|
-
it { Delete.(params: {}, current_user: anonymous).inspect("x").must_equal %{<Result:true [true] >} }
|
239
|
-
it { Delete.(params: {}, current_user: admin) .inspect("x").must_equal %{<Result:true [nil] >} }
|
240
|
-
end
|
241
|
-
|
242
|
-
class NestedWithCallableAndInputTest < Minitest::Spec
|
243
|
-
Memo = Struct.new(:title, :text, :created_by)
|
244
|
-
|
245
|
-
class Memo::Upsert < Trailblazer::Operation
|
246
|
-
step Nested( :operation_class, input: :input_for_create )
|
247
|
-
|
248
|
-
def operation_class( ctx, ** )
|
249
|
-
ctx[:id] ? Update : Create
|
250
|
-
end
|
251
|
-
|
252
|
-
# only let :title pass through.
|
253
|
-
def input_for_create( ctx )
|
254
|
-
{ title: ctx[:title] }
|
255
|
-
end
|
256
|
-
|
257
|
-
class Create < Trailblazer::Operation
|
258
|
-
step :create_memo
|
259
|
-
|
260
|
-
def create_memo( ctx, ** )
|
261
|
-
ctx[:model] = Memo.new(ctx[:title], ctx[:text], :create)
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
class Update < Trailblazer::Operation
|
266
|
-
step :find_by_title
|
267
|
-
|
268
|
-
def find_by_title( ctx, ** )
|
269
|
-
ctx[:model] = Memo.new(ctx[:title], ctx[:text], :update)
|
270
|
-
end
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
it "runs Create without :id" do
|
275
|
-
Memo::Upsert.( title: "Yay!" ).inspect(:model).
|
276
|
-
must_equal %{<Result:true [#<struct NestedWithCallableAndInputTest::Memo title=\"Yay!\", text=nil, created_by=:create>] >}
|
277
|
-
end
|
278
|
-
|
279
|
-
it "runs Update without :id" do
|
280
|
-
Memo::Upsert.( id: 1, title: "Yay!" ).inspect(:model).
|
281
|
-
must_equal %{<Result:true [#<struct NestedWithCallableAndInputTest::Memo title=\"Yay!\", text=nil, created_by=:update>] >}
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
# builder: Nested + deviate to left if nil / skip_track if true
|
286
|
-
|
287
|
-
#---
|
288
|
-
# automatic :name
|
289
|
-
class NestedNameTest < Minitest::Spec
|
290
|
-
class Create < Trailblazer::Operation
|
291
|
-
class Present < Trailblazer::Operation
|
292
|
-
# ...
|
293
|
-
end
|
294
|
-
|
295
|
-
step Nested( Present )
|
296
|
-
# ...
|
297
|
-
end
|
298
|
-
|
299
|
-
it { Operation::Inspect.(Create).must_equal %{[>>Nested(NestedNameTest::Create::Present)]} }
|
300
|
-
end
|
data/test/docs/policy_test.rb
DELETED
data/test/docs/pundit_test.rb
DELETED
@@ -1,133 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
#:policy
|
4
|
-
class MyPolicy
|
5
|
-
def initialize(user, model)
|
6
|
-
@user, @model = user, model
|
7
|
-
end
|
8
|
-
|
9
|
-
def create?
|
10
|
-
@user == Module && @model.id.nil?
|
11
|
-
end
|
12
|
-
|
13
|
-
def new?
|
14
|
-
@user == Class
|
15
|
-
end
|
16
|
-
end
|
17
|
-
#:policy end
|
18
|
-
|
19
|
-
#--
|
20
|
-
# with policy
|
21
|
-
class DocsPunditProcTest < Minitest::Spec
|
22
|
-
Song = Struct.new(:id)
|
23
|
-
|
24
|
-
#:pundit
|
25
|
-
class Create < Trailblazer::Operation
|
26
|
-
step Model( Song, :new )
|
27
|
-
step Policy::Pundit( MyPolicy, :create? )
|
28
|
-
# ...
|
29
|
-
end
|
30
|
-
#:pundit end
|
31
|
-
|
32
|
-
it { Trailblazer::Operation::Inspect.(Create).must_equal %{[>model.build,>policy.default.eval]} }
|
33
|
-
it { Create.(params: {}, current_user: Module).inspect(:model).must_equal %{<Result:true [#<struct DocsPunditProcTest::Song id=nil>] >} }
|
34
|
-
it { Create.(params: {} ).inspect(:model).must_equal %{<Result:false [#<struct DocsPunditProcTest::Song id=nil>] >} }
|
35
|
-
|
36
|
-
it do
|
37
|
-
#:pundit-result
|
38
|
-
result = Create.(params: {}, current_user: Module)
|
39
|
-
result["result.policy.default"].success? #=> true
|
40
|
-
result["result.policy.default"]["policy"] #=> #<MyPolicy ...>
|
41
|
-
#:pundit-result end
|
42
|
-
result["result.policy.default"].success?.must_equal true
|
43
|
-
result["result.policy.default"]["policy"].is_a?(MyPolicy).must_equal true
|
44
|
-
end
|
45
|
-
|
46
|
-
#---
|
47
|
-
#- override
|
48
|
-
class New < Create
|
49
|
-
step Policy::Pundit( MyPolicy, :new? ), override: true
|
50
|
-
end
|
51
|
-
|
52
|
-
it { Trailblazer::Operation::Inspect.(New).must_equal %{[>model.build,>policy.default.eval]} }
|
53
|
-
it { New.(params: {}, current_user: Class ).inspect(:model).must_equal %{<Result:true [#<struct DocsPunditProcTest::Song id=nil>] >} }
|
54
|
-
it { New.(params: {}, current_user: nil ).inspect(:model).must_equal %{<Result:false [#<struct DocsPunditProcTest::Song id=nil>] >} }
|
55
|
-
|
56
|
-
#---
|
57
|
-
#- override with :name
|
58
|
-
class Edit < Trailblazer::Operation
|
59
|
-
step Policy::Pundit( MyPolicy, :create?, name: "first" )
|
60
|
-
step Policy::Pundit( MyPolicy, :new?, name: "second" )
|
61
|
-
end
|
62
|
-
|
63
|
-
class Update < Edit
|
64
|
-
step Policy::Pundit( MyPolicy, :new?, name: "first" ), override: true
|
65
|
-
end
|
66
|
-
|
67
|
-
it { Trailblazer::Operation::Inspect.(Edit).must_equal %{[>policy.first.eval,>policy.second.eval]} }
|
68
|
-
it { Edit.(params: {}, current_user: Class).inspect(:model).must_equal %{<Result:false [nil] >} }
|
69
|
-
it { Trailblazer::Operation::Inspect.(Update).must_equal %{[>policy.first.eval,>policy.second.eval]} }
|
70
|
-
it { Update.(params: {}, current_user: Class).inspect(:model).must_equal %{<Result:true [nil] >} }
|
71
|
-
|
72
|
-
#---
|
73
|
-
# dependency injection
|
74
|
-
class AnotherPolicy < MyPolicy
|
75
|
-
def create?
|
76
|
-
true
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
it {
|
81
|
-
result =
|
82
|
-
#:di-call
|
83
|
-
Create.(params: {},
|
84
|
-
current_user: Module,
|
85
|
-
"policy.default.eval" => Trailblazer::Operation::Policy::Pundit.build(AnotherPolicy, :create?)
|
86
|
-
)
|
87
|
-
#:di-call end
|
88
|
-
result.inspect("").must_equal %{<Result:true [nil] >} }
|
89
|
-
end
|
90
|
-
|
91
|
-
#-
|
92
|
-
# with name:
|
93
|
-
class PunditWithNameTest < Minitest::Spec
|
94
|
-
Song = Struct.new(:id)
|
95
|
-
|
96
|
-
#:name
|
97
|
-
class Create < Trailblazer::Operation
|
98
|
-
step Model( Song, :new )
|
99
|
-
step Policy::Pundit( MyPolicy, :create?, name: "after_model" )
|
100
|
-
# ...
|
101
|
-
end
|
102
|
-
#:name end
|
103
|
-
|
104
|
-
it {
|
105
|
-
#:name-call
|
106
|
-
result = Create.(params: {}, current_user: Module)
|
107
|
-
result["result.policy.after_model"].success? #=> true
|
108
|
-
#:name-call end
|
109
|
-
result["result.policy.after_model"].success?.must_equal true }
|
110
|
-
end
|
111
|
-
|
112
|
-
#---
|
113
|
-
# class-level guard
|
114
|
-
# class DocsGuardClassLevelTest < Minitest::Spec
|
115
|
-
# #:class-level
|
116
|
-
# class Create < Trailblazer::Operation
|
117
|
-
# step Policy::Guard[ ->(options) { options["current_user"] == Module } ],
|
118
|
-
# before: "operation.new"
|
119
|
-
# #~pipe--only
|
120
|
-
# step ->(options) { options["x"] = true }
|
121
|
-
# #~pipe--only end
|
122
|
-
# end
|
123
|
-
# #:class-level end
|
124
|
-
|
125
|
-
# it { Create.(); Create["result.policy"].must_be_nil }
|
126
|
-
# it { Create.(params: {}, current_user: Module)["x"].must_equal true }
|
127
|
-
# it { Create.(params: {} )["x"].must_be_nil }
|
128
|
-
# end
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
# TODO:
|
133
|
-
#policy.default
|