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,24 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
require "trailblazer/operation/present"
|
4
|
+
|
5
|
+
class PresentTest < Minitest::Spec
|
6
|
+
class Create < Trailblazer::Operation
|
7
|
+
include Test::ReturnCall
|
8
|
+
include Present
|
9
|
+
|
10
|
+
include Model::Builder
|
11
|
+
def model!(*); Object end
|
12
|
+
|
13
|
+
def call(params)
|
14
|
+
"#call run!"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it do
|
19
|
+
result = Create.present
|
20
|
+
result["model"].must_equal Object
|
21
|
+
end
|
22
|
+
|
23
|
+
it { Create.().must_equal "#call run!" }
|
24
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "trailblazer/operation/policy"
|
3
|
+
|
4
|
+
class PolicyTest < Minitest::Spec
|
5
|
+
Song = Struct.new(:id) do
|
6
|
+
def self.find(id); new(id) end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Auth
|
10
|
+
def initialize(user, model); @user, @model = user, model end
|
11
|
+
def only_user?; @user == Module && @model.nil? end
|
12
|
+
def user_object?; @user == Object end
|
13
|
+
def user_and_model?; @user == Module && @model.class == Song end
|
14
|
+
def inspect; "<Auth: user:#{@user.inspect}, model:#{@model.inspect}>" end
|
15
|
+
end
|
16
|
+
|
17
|
+
#---
|
18
|
+
# Instance-level: Only policy, no model
|
19
|
+
class Create < Trailblazer::Operation
|
20
|
+
self.| Policy::Pundit( Auth, :only_user? )
|
21
|
+
self.| :process
|
22
|
+
|
23
|
+
def process(*)
|
24
|
+
self["process"] = true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# successful.
|
29
|
+
it do
|
30
|
+
result = Create.({}, "current_user" => Module)
|
31
|
+
result["process"].must_equal true
|
32
|
+
#- result object, policy
|
33
|
+
result["result.policy.default"].success?.must_equal true
|
34
|
+
result["result.policy.default"]["message"].must_equal nil
|
35
|
+
# result[:valid].must_equal nil
|
36
|
+
result["policy.default"].inspect.must_equal %{<Auth: user:Module, model:nil>}
|
37
|
+
end
|
38
|
+
# breach.
|
39
|
+
it do
|
40
|
+
result = Create.({}, "current_user" => nil)
|
41
|
+
result["process"].must_equal nil
|
42
|
+
#- result object, policy
|
43
|
+
result["result.policy.default"].success?.must_equal false
|
44
|
+
result["result.policy.default"]["message"].must_equal "Breach"
|
45
|
+
end
|
46
|
+
# inject different policy.Condition it { Create.({}, "current_user" => Object, "policy.default.eval" => Trailblazer::Operation::Policy::Pundit::Condition.new(Auth, :user_object?))["process"].must_equal true }
|
47
|
+
it { Create.({}, "current_user" => Module, "policy.default.eval" => Trailblazer::Operation::Policy::Pundit::Condition.new(Auth, :user_object?))["process"].must_equal nil }
|
48
|
+
|
49
|
+
|
50
|
+
#---
|
51
|
+
# inheritance, adding Model
|
52
|
+
class Show < Create
|
53
|
+
self.| Model( Song, :new ), before: "policy.default.eval"
|
54
|
+
end
|
55
|
+
|
56
|
+
it { Show["pipetree"].inspect.must_equal %{[>>operation.new,&model.build,&policy.default.eval,>process]} }
|
57
|
+
|
58
|
+
# invalid because user AND model.
|
59
|
+
it do
|
60
|
+
result = Show.({}, "current_user" => Module)
|
61
|
+
result["process"].must_equal nil
|
62
|
+
result["model"].inspect.must_equal %{#<struct PolicyTest::Song id=nil>}
|
63
|
+
# result["policy"].inspect.must_equal %{#<struct PolicyTest::Song id=nil>}
|
64
|
+
end
|
65
|
+
|
66
|
+
# valid because new policy.
|
67
|
+
it do
|
68
|
+
# puts Show["pipetree"].inspect
|
69
|
+
result = Show.({}, "current_user" => Module, "policy.default.eval" => Trailblazer::Operation::Policy::Pundit::Condition.new(Auth, :user_and_model?))
|
70
|
+
result["process"].must_equal true
|
71
|
+
result["model"].inspect.must_equal %{#<struct PolicyTest::Song id=nil>}
|
72
|
+
result["policy.default"].inspect.must_equal %{<Auth: user:Module, model:#<struct PolicyTest::Song id=nil>>}
|
73
|
+
end
|
74
|
+
|
75
|
+
##--
|
76
|
+
# TOOOODOOO: Policy and Model before Build ("External" or almost Resolver)
|
77
|
+
class Edit < Trailblazer::Operation
|
78
|
+
self.| Model Song, :update
|
79
|
+
self.| Policy::Pundit( Auth, :user_and_model? )
|
80
|
+
self.| :process
|
81
|
+
|
82
|
+
def process(*); self["process"] = true end
|
83
|
+
end
|
84
|
+
|
85
|
+
# successful.
|
86
|
+
it do
|
87
|
+
result = Edit.({ id: 1 }, "current_user" => Module)
|
88
|
+
result["process"].must_equal true
|
89
|
+
result["model"].inspect.must_equal %{#<struct PolicyTest::Song id=1>}
|
90
|
+
result["result.policy.default"].success?.must_equal true
|
91
|
+
result["result.policy.default"]["message"].must_equal nil
|
92
|
+
# result[:valid].must_equal nil
|
93
|
+
result["policy.default"].inspect.must_equal %{<Auth: user:Module, model:#<struct PolicyTest::Song id=1>>}
|
94
|
+
end
|
95
|
+
|
96
|
+
# breach.
|
97
|
+
it do
|
98
|
+
result = Edit.({ id: 4 }, "current_user" => nil)
|
99
|
+
result["model"].inspect.must_equal %{#<struct PolicyTest::Song id=4>}
|
100
|
+
result["process"].must_equal nil
|
101
|
+
result["result.policy.default"].success?.must_equal false
|
102
|
+
result["result.policy.default"]["message"].must_equal "Breach"
|
103
|
+
end
|
104
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require "test_helper"
|
2
|
-
|
3
2
|
require "representable/json"
|
4
3
|
|
5
4
|
class RepresenterTest < MiniTest::Spec
|
@@ -7,8 +6,10 @@ class RepresenterTest < MiniTest::Spec
|
|
7
6
|
Artist = Struct.new(:name)
|
8
7
|
|
9
8
|
class Create < Trailblazer::Operation
|
10
|
-
|
9
|
+
include Contract::Explicit
|
11
10
|
include Representer
|
11
|
+
include Representer::InferFromContract
|
12
|
+
attr_reader :model # FIXME: all we want is #model.
|
12
13
|
|
13
14
|
contract do
|
14
15
|
property :title
|
@@ -19,18 +20,19 @@ class RepresenterTest < MiniTest::Spec
|
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
22
|
-
def
|
23
|
-
|
24
|
-
validate(params[:album],
|
23
|
+
def call(params)
|
24
|
+
self["model"] = Album.new # NO artist!!!
|
25
|
+
validate(params[:album], model: self["model"])
|
26
|
+
self
|
25
27
|
end
|
26
28
|
end
|
27
29
|
|
28
30
|
|
29
31
|
# Infers representer from contract, no customization.
|
30
32
|
class Show < Create
|
31
|
-
def
|
32
|
-
|
33
|
-
|
33
|
+
def call(params)
|
34
|
+
self["model"] = Album.new("After The War", Artist.new("Gary Moore"))
|
35
|
+
self
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
@@ -46,36 +48,32 @@ class RepresenterTest < MiniTest::Spec
|
|
46
48
|
end
|
47
49
|
|
48
50
|
class HypermediaShow < HypermediaCreate
|
49
|
-
def
|
50
|
-
|
51
|
-
|
51
|
+
def call(params)
|
52
|
+
self["model"] = Album.new("After The War", Artist.new("Gary Moore"))
|
53
|
+
self
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
55
57
|
|
56
58
|
# rendering
|
57
59
|
# generic contract -> representer
|
58
|
-
it
|
59
|
-
res, op = Show.run({})
|
60
|
-
op.to_json.must_equal %{{"title":"After The War","artist":{"name":"Gary Moore"}}}
|
61
|
-
end
|
60
|
+
it { Show.().to_json.must_equal %{{"title":"After The War","artist":{"name":"Gary Moore"}}} }
|
62
61
|
|
63
62
|
# contract -> representer with hypermedia
|
64
63
|
it do
|
65
|
-
|
66
|
-
op.to_json.must_equal %{{"title":"After The War","artist":{"name":"Gary Moore"},"_links":{"self":{"href":"//album/After The War"}}}}
|
64
|
+
HypermediaShow.().to_json.must_equal %{{"title":"After The War","artist":{"name":"Gary Moore"},"_links":{"self":{"href":"//album/After The War"}}}}
|
67
65
|
end
|
68
66
|
|
69
67
|
|
70
68
|
# parsing
|
71
69
|
it do
|
72
|
-
|
70
|
+
op = Create.(album: %{{"title":"Run For Cover","artist":{"name":"Gary Moore"}}})
|
73
71
|
op.contract.title.must_equal "Run For Cover"
|
74
72
|
op.contract.artist.name.must_equal "Gary Moore"
|
75
73
|
end
|
76
74
|
|
77
75
|
it do
|
78
|
-
|
76
|
+
op = HypermediaCreate.(album: %{{"title":"After The War","artist":{"name":"Gary Moore"},"_links":{"self":{"href":"//album/After The War"}}}})
|
79
77
|
op.contract.title.must_equal "After The War"
|
80
78
|
op.contract.artist.name.must_equal "Gary Moore"
|
81
79
|
end
|
@@ -87,7 +85,9 @@ class RepresenterTest < MiniTest::Spec
|
|
87
85
|
# explicit representer set with ::representer_class=.
|
88
86
|
require "roar/decorator"
|
89
87
|
class JsonApiCreate < Trailblazer::Operation
|
88
|
+
include Contract::Explicit
|
90
89
|
include Representer
|
90
|
+
attr_reader :model
|
91
91
|
|
92
92
|
contract do # we still need contract as the representer writes to the contract twin.
|
93
93
|
property :title
|
@@ -97,31 +97,33 @@ class RepresenterTest < MiniTest::Spec
|
|
97
97
|
include Roar::JSON
|
98
98
|
property :title
|
99
99
|
end
|
100
|
-
self.representer_class = AlbumRepresenter
|
101
100
|
|
102
|
-
|
103
|
-
|
104
|
-
|
101
|
+
# FIXME: this won't inherit, of course.
|
102
|
+
# self["representer.class"] = AlbumRepresenter
|
103
|
+
representer AlbumRepresenter
|
104
|
+
|
105
|
+
def call(params)
|
106
|
+
self["model"] = Album.new # NO artist!!!
|
107
|
+
validate(params[:album], model: self["model"])
|
108
|
+
self
|
105
109
|
end
|
106
110
|
end
|
107
111
|
|
108
112
|
class JsonApiShow < JsonApiCreate
|
109
|
-
def
|
110
|
-
|
111
|
-
|
113
|
+
def call(params)
|
114
|
+
self["model"] = Album.new("After The War", Artist.new("Gary Moore"))
|
115
|
+
self
|
112
116
|
end
|
113
117
|
end
|
114
118
|
|
115
119
|
# render.
|
116
120
|
it do
|
117
|
-
|
118
|
-
op.to_json.must_equal %{{"title":"After The War"}}
|
121
|
+
JsonApiShow.().to_json.must_equal %{{"title":"After The War"}}
|
119
122
|
end
|
120
123
|
|
121
124
|
# parse.
|
122
125
|
it do
|
123
|
-
|
124
|
-
op.contract.title.must_equal "Run For Cover"
|
126
|
+
JsonApiCreate.(album: %{{"title":"Run For Cover"}}).contract.title.must_equal "Run For Cover"
|
125
127
|
end
|
126
128
|
end
|
127
129
|
|
@@ -130,26 +132,35 @@ class InternalRepresenterAPITest < MiniTest::Spec
|
|
130
132
|
|
131
133
|
describe "#represented" do
|
132
134
|
class Show < Trailblazer::Operation
|
135
|
+
include Contract::Explicit
|
133
136
|
include Representer, Model
|
134
137
|
model Song, :create
|
135
138
|
|
136
139
|
representer do
|
137
140
|
property :class
|
138
141
|
end
|
142
|
+
|
143
|
+
def call(*)
|
144
|
+
self
|
145
|
+
end
|
146
|
+
|
147
|
+
def model # FIXME.
|
148
|
+
self["model"]
|
149
|
+
end
|
139
150
|
end
|
140
151
|
|
141
152
|
it "uses #model as represented, per default" do
|
142
|
-
Show.
|
153
|
+
Show.({}).to_json.must_equal '{"class":"InternalRepresenterAPITest::Song"}'
|
143
154
|
end
|
144
155
|
|
145
156
|
class ShowContract < Show
|
146
157
|
def represented
|
147
|
-
|
158
|
+
"Object"
|
148
159
|
end
|
149
160
|
end
|
150
161
|
|
151
162
|
it "can be overriden to use the contract" do
|
152
|
-
ShowContract.
|
163
|
+
ShowContract.({}).to_json.must_equal %{{"class":"String"}}
|
153
164
|
end
|
154
165
|
end
|
155
166
|
|
@@ -163,16 +174,17 @@ class InternalRepresenterAPITest < MiniTest::Spec
|
|
163
174
|
end
|
164
175
|
|
165
176
|
def to_json(*)
|
166
|
-
super(
|
177
|
+
super(self["params"])
|
167
178
|
end
|
168
179
|
|
169
|
-
|
180
|
+
include Model::Builder
|
181
|
+
def model!(*)
|
170
182
|
Song.new(1)
|
171
183
|
end
|
172
184
|
end
|
173
185
|
|
174
186
|
it "allows to pass options to #to_json" do
|
175
|
-
OptionsShow.
|
187
|
+
OptionsShow.(include: [:id]).to_json.must_equal %{{"id":1}}
|
176
188
|
end
|
177
189
|
end
|
178
190
|
end
|
@@ -182,6 +194,7 @@ class DifferentParseAndRenderingRepresenterTest < MiniTest::Spec
|
|
182
194
|
|
183
195
|
# rendering
|
184
196
|
class Create < Trailblazer::Operation
|
197
|
+
include Contract::Explicit
|
185
198
|
extend Representer::DSL
|
186
199
|
include Representer::Rendering # no Deserializer::Hash here or anything.
|
187
200
|
|
@@ -193,11 +206,12 @@ class DifferentParseAndRenderingRepresenterTest < MiniTest::Spec
|
|
193
206
|
property :title, as: :Title
|
194
207
|
end
|
195
208
|
|
196
|
-
def
|
197
|
-
|
209
|
+
def call(params)
|
210
|
+
self["model"] = Album.new
|
198
211
|
validate(params) do
|
199
212
|
contract.sync
|
200
213
|
end
|
214
|
+
self
|
201
215
|
end
|
202
216
|
end
|
203
217
|
|
@@ -207,6 +221,7 @@ class DifferentParseAndRenderingRepresenterTest < MiniTest::Spec
|
|
207
221
|
|
208
222
|
# parsing
|
209
223
|
class Update < Trailblazer::Operation
|
224
|
+
include Contract::Explicit
|
210
225
|
extend Representer::DSL
|
211
226
|
include Representer::Deserializer::Hash # no Rendering.
|
212
227
|
|
@@ -218,17 +233,18 @@ class DifferentParseAndRenderingRepresenterTest < MiniTest::Spec
|
|
218
233
|
property :title
|
219
234
|
end
|
220
235
|
|
221
|
-
|
222
|
-
|
223
|
-
@model = Album.new
|
236
|
+
def call(params)
|
237
|
+
self["model"] = Album.new
|
224
238
|
|
225
239
|
validate(params) do
|
226
240
|
contract.sync
|
227
241
|
end
|
242
|
+
|
243
|
+
self
|
228
244
|
end
|
229
245
|
|
230
246
|
def to_json(*)
|
231
|
-
%{{"title": "#{model.title}"}}
|
247
|
+
%{{"title": "#{self["model"].title}"}}
|
232
248
|
end
|
233
249
|
end
|
234
250
|
|
@@ -1,83 +1,47 @@
|
|
1
1
|
require "test_helper"
|
2
|
-
require "trailblazer/operation/resolver"
|
3
2
|
|
4
|
-
class ResolverTest <
|
5
|
-
Song = Struct.new(:
|
6
|
-
|
7
|
-
|
8
|
-
class MyKitchenRules
|
9
|
-
def initialize(user, song)
|
10
|
-
@user = user
|
11
|
-
@song = song
|
12
|
-
end
|
13
|
-
|
14
|
-
def create?
|
15
|
-
@user.is_a?(User) and @song.is_a?(Song)
|
16
|
-
end
|
17
|
-
|
18
|
-
def admin?
|
19
|
-
@user && @user.name == "admin" && @song.is_a?(Song)
|
20
|
-
end
|
21
|
-
|
22
|
-
def true?
|
23
|
-
true
|
24
|
-
end
|
3
|
+
class ResolverTest < Minitest::Spec
|
4
|
+
Song = Struct.new(:id) do
|
5
|
+
def self.find(id); new(id) end
|
25
6
|
end
|
26
7
|
|
27
|
-
class
|
28
|
-
|
29
|
-
model
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
return Admin if policy.admin?
|
35
|
-
return SignedIn if params[:current_user] && params[:current_user].name
|
36
|
-
end
|
8
|
+
class Auth
|
9
|
+
def initialize(*args); @user, @model = *args end
|
10
|
+
def only_user?; @user == Module && @model.nil? end
|
11
|
+
def user_object?; @user == Object end
|
12
|
+
def user_and_model?; @user == Module && @model.class == Song end
|
13
|
+
def inspect; "<Auth: user:#{@user.inspect}, model:#{@model.inspect}>" end
|
14
|
+
end
|
37
15
|
|
38
|
-
|
39
|
-
|
40
|
-
|
16
|
+
class A < Trailblazer::Operation
|
17
|
+
extend Builder::DSL
|
18
|
+
builds ->(options) {
|
19
|
+
return P if options["params"] == { some: "params", id:1 }
|
20
|
+
return B if options["policy.default"].inspect == %{<Auth: user:Module, model:#<struct ResolverTest::Song id=3>>} # both user and model:id are set!
|
21
|
+
return M if options["model"].inspect == %{#<struct ResolverTest::Song id=9>}
|
22
|
+
}
|
41
23
|
|
42
|
-
|
43
|
-
|
24
|
+
self.| Model( Song, :update ), before: "operation.new"
|
25
|
+
self.| Policy::Pundit( Auth, :user_and_model? ), before: "operation.new"
|
26
|
+
require "trailblazer/operation/resolver"
|
27
|
+
self.| Resolver(), before: "operation.new"
|
44
28
|
|
45
|
-
|
46
|
-
end
|
47
|
-
class SignedIn < self
|
48
|
-
end
|
49
|
-
end
|
29
|
+
self.| :process
|
50
30
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
it { Create.({current_user: User.new("kenneth")}).must_be_instance_of Create::SignedIn }
|
31
|
+
class P < self; end
|
32
|
+
class B < self; end
|
33
|
+
class M < self; end
|
55
34
|
|
56
|
-
|
57
|
-
it do
|
58
|
-
assert_raises Trailblazer::NotAuthorizedError do
|
59
|
-
Create.({})
|
60
|
-
end
|
35
|
+
def process(*); self["x"] = self.class end
|
61
36
|
end
|
62
37
|
|
38
|
+
it { A["pipetree"].inspect.must_equal %{[&model.build,&policy.default.eval,>>builder.call,>>operation.new,>process]} }
|
63
39
|
|
64
|
-
|
65
|
-
|
66
|
-
include Resolver
|
67
|
-
model Song, :create
|
68
|
-
policy MyKitchenRules, :true?
|
69
|
-
|
70
|
-
builds-> (model, policy, params) do
|
71
|
-
policy.instance_eval { def whoami; "me!" end }
|
72
|
-
nil
|
73
|
-
end
|
40
|
+
it { r=A.({ some: "params", id: 1 }, { "current_user" => Module })
|
41
|
+
puts r.inspect
|
74
42
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
Update.({}).policy.whoami.must_equal "me!"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
43
|
+
}
|
44
|
+
it { A.({ some: "params", id: 1 }, { "current_user" => Module })["x"].must_equal A::P }
|
45
|
+
it { A.({ id: 3 }, { "current_user" => Module })["x"].must_equal A::B }
|
46
|
+
it { A.({ id: 9 }, { "current_user" => Module })["x"].must_equal A::M }
|
47
|
+
end
|