trailblazer 2.0.7 → 2.1.0
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 +5 -5
- data/.gitignore +1 -0
- data/.rubocop-https---raw-githubusercontent-com-trailblazer-meta-master-rubocop-yml +101 -0
- data/.rubocop.yml +20 -0
- data/.rubocop_todo.yml +556 -0
- data/.travis.yml +6 -10
- data/CHANGES.md +83 -1
- data/COMM-LICENSE +46 -75
- data/CONTRIBUTING.md +179 -0
- data/Gemfile +0 -27
- data/{LICENSE.txt → LICENSE} +4 -4
- data/README.md +39 -138
- data/Rakefile +2 -19
- data/lib/trailblazer.rb +3 -17
- data/lib/trailblazer/version.rb +3 -1
- data/test/test_helper.rb +12 -3
- data/trailblazer.gemspec +10 -14
- metadata +22 -147
- data/doc/Trb-The-Stack.png +0 -0
- data/doc/operation-2017.png +0 -0
- data/doc/trb.jpg +0 -0
- data/lib/trailblazer/dsl.rb +0 -47
- data/lib/trailblazer/operation/auto_inject.rb +0 -47
- data/lib/trailblazer/operation/callback.rb +0 -35
- data/lib/trailblazer/operation/contract.rb +0 -46
- data/lib/trailblazer/operation/guard.rb +0 -18
- data/lib/trailblazer/operation/model.rb +0 -60
- data/lib/trailblazer/operation/module.rb +0 -29
- data/lib/trailblazer/operation/nested.rb +0 -113
- data/lib/trailblazer/operation/persist.rb +0 -10
- data/lib/trailblazer/operation/policy.rb +0 -35
- data/lib/trailblazer/operation/procedural/contract.rb +0 -15
- data/lib/trailblazer/operation/procedural/validate.rb +0 -22
- data/lib/trailblazer/operation/pundit.rb +0 -38
- data/lib/trailblazer/operation/representer.rb +0 -31
- data/lib/trailblazer/operation/rescue.rb +0 -21
- data/lib/trailblazer/operation/test.rb +0 -17
- data/lib/trailblazer/operation/validate.rb +0 -68
- data/lib/trailblazer/operation/wrap.rb +0 -25
- data/test/docs/auto_inject_test.rb +0 -30
- data/test/docs/contract_test.rb +0 -525
- data/test/docs/dry_test.rb +0 -31
- data/test/docs/fast_test.rb +0 -164
- data/test/docs/guard_test.rb +0 -169
- data/test/docs/macro_test.rb +0 -36
- data/test/docs/model_test.rb +0 -75
- data/test/docs/nested_test.rb +0 -334
- data/test/docs/operation_test.rb +0 -408
- 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 -183
- data/test/gemfiles/Gemfile.ruby-1.9 +0 -3
- data/test/gemfiles/Gemfile.ruby-2.0 +0 -12
- data/test/gemfiles/Gemfile.ruby-2.3 +0 -12
- data/test/module_test.rb +0 -100
- data/test/operation/callback_test.rb +0 -70
- data/test/operation/contract_test.rb +0 -420
- data/test/operation/dsl/callback_test.rb +0 -106
- data/test/operation/dsl/contract_test.rb +0 -294
- data/test/operation/dsl/representer_test.rb +0 -169
- data/test/operation/model_test.rb +0 -60
- data/test/operation/params_test.rb +0 -36
- data/test/operation/persist_test.rb +0 -44
- data/test/operation/pipedream_test.rb +0 -59
- data/test/operation/pipetree_test.rb +0 -104
- data/test/operation/present_test.rb +0 -24
- data/test/operation/pundit_test.rb +0 -104
- data/test/operation/representer_test.rb +0 -254
- data/test/operation/resolver_test.rb +0 -47
- data/test/operation_test.rb +0 -143
@@ -1,106 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class DslCallbackTest < MiniTest::Spec
|
4
|
-
module SongProcess
|
5
|
-
def _invocations
|
6
|
-
self["x"] ||= []
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.included(includer)
|
10
|
-
includer.extend Trailblazer::Operation::Contract::DSL
|
11
|
-
includer.contract do
|
12
|
-
property :title
|
13
|
-
end
|
14
|
-
includer.| Trailblazer::Operation::Model[OpenStruct, :new]
|
15
|
-
includer.| Trailblazer::Operation::Contract::Build[includer["contract.default.class"]]
|
16
|
-
includer.| Trailblazer::Operation::Contract::Validate[]
|
17
|
-
includer.| Trailblazer::Operation::Callback[:default]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe "inheritance across operations" do
|
22
|
-
class Operation < Trailblazer::Operation
|
23
|
-
extend Callback::DSL
|
24
|
-
include SongProcess
|
25
|
-
|
26
|
-
callback do
|
27
|
-
on_change :default!
|
28
|
-
end
|
29
|
-
|
30
|
-
class Admin < self
|
31
|
-
callback do
|
32
|
-
on_change :admin_default!
|
33
|
-
end
|
34
|
-
|
35
|
-
callback(:after_save) { on_change :after_save! }
|
36
|
-
|
37
|
-
def admin_default!(*); _invocations << :admin_default!; end
|
38
|
-
def after_save!(*); _invocations << :after_save!; end
|
39
|
-
|
40
|
-
step Trailblazer::Operation::Callback[:after_save]
|
41
|
-
end
|
42
|
-
|
43
|
-
def default!(*); _invocations << :default!; end
|
44
|
-
end
|
45
|
-
|
46
|
-
it { Operation.({"title"=> "Love-less"})["x"].must_equal([:default!]) }
|
47
|
-
it { Operation::Admin.({"title"=> "Love-less"})["x"].must_equal([:default!, :admin_default!, :after_save!]) }
|
48
|
-
end
|
49
|
-
|
50
|
-
describe "Op.callback :after_save, AfterSaveCallback" do
|
51
|
-
class AfterSaveCallback < Disposable::Callback::Group
|
52
|
-
on_change :after_save!
|
53
|
-
|
54
|
-
def after_save!(twin, options)
|
55
|
-
options[:operation]._invocations << :after_save!
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
class OpWithExternalCallback < Trailblazer::Operation
|
60
|
-
include SongProcess
|
61
|
-
extend Callback::DSL
|
62
|
-
callback :after_save, AfterSaveCallback
|
63
|
-
|
64
|
-
step Callback[:after_save]
|
65
|
-
end
|
66
|
-
|
67
|
-
it { OpWithExternalCallback.("title"=>"Thunder Rising").must_equal([:after_save!]) }
|
68
|
-
end
|
69
|
-
|
70
|
-
describe "Op.callback :after_save, AfterSaveCallback do .. end" do
|
71
|
-
class DefaultCallback < Disposable::Callback::Group
|
72
|
-
on_change :default!
|
73
|
-
|
74
|
-
def default!(twin, options)
|
75
|
-
options[:operation]._invocations << :default!
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
class OpUsingCallback < Trailblazer::Operation
|
80
|
-
extend Callback::DSL
|
81
|
-
include SongProcess
|
82
|
-
callback :default, DefaultCallback
|
83
|
-
end
|
84
|
-
|
85
|
-
class OpExtendingCallback < Trailblazer::Operation
|
86
|
-
extend Callback::DSL
|
87
|
-
include SongProcess
|
88
|
-
callback :default, DefaultCallback do
|
89
|
-
on_change :after_save!
|
90
|
-
|
91
|
-
def default!(twin, options)
|
92
|
-
options[:operation]._invocations << :extended_default!
|
93
|
-
end
|
94
|
-
|
95
|
-
def after_save!(twin, options)
|
96
|
-
options[:operation]._invocations << :after_save!
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
# this operation copies DefaultCallback and shouldn't run #after_save!.
|
102
|
-
it { OpUsingCallback.(title: "Thunder Rising")["x"].must_equal([:default!]) }
|
103
|
-
# this operation copies DefaultCallback, extends it and runs #after_save!.
|
104
|
-
it { OpExtendingCallback.(title: "Thunder Rising")["x"].must_equal([:extended_default!, :after_save!]) }
|
105
|
-
end
|
106
|
-
end
|
@@ -1,294 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
require "trailblazer/operation/contract"
|
3
|
-
|
4
|
-
# contract Constant # new
|
5
|
-
# contract Constant, inherit: true # extend existing
|
6
|
-
# contract do end # extend existing || new
|
7
|
-
# contract Constant do .. end # new, extend new
|
8
|
-
|
9
|
-
class DslContractTest < MiniTest::Spec
|
10
|
-
module Call
|
11
|
-
def call(params)
|
12
|
-
validate(params, model: model=OpenStruct.new) { contract.sync }
|
13
|
-
model
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.included(includer)
|
17
|
-
includer.step Trailblazer::Operation::Model( OpenStruct, :new )
|
18
|
-
includer.step Trailblazer::Operation::Contract::Build()
|
19
|
-
includer.step Trailblazer::Operation::Contract::Validate()
|
20
|
-
includer.step Trailblazer::Operation::Contract::Persist( method: :sync )
|
21
|
-
# includer.> ->(op, *) { op["x"] = [] }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# ---
|
26
|
-
# Operation::["contract.default.class"]
|
27
|
-
# Operation::["contract.default.class"]=
|
28
|
-
class Create < Trailblazer::Operation
|
29
|
-
include Contract
|
30
|
-
self["contract.default.class"] = String
|
31
|
-
end
|
32
|
-
|
33
|
-
# reader method.
|
34
|
-
# no subclassing.
|
35
|
-
it { Create["contract.default.class"].must_equal String }
|
36
|
-
|
37
|
-
class CreateOrFind < Create
|
38
|
-
end
|
39
|
-
|
40
|
-
# no inheritance with setter.
|
41
|
-
it { CreateOrFind["contract.default.class"].must_equal nil }
|
42
|
-
|
43
|
-
# ---
|
44
|
-
# Op::contract Constant
|
45
|
-
class Update < Trailblazer::Operation
|
46
|
-
class IdContract < Reform::Form
|
47
|
-
property :id
|
48
|
-
end
|
49
|
-
|
50
|
-
extend Contract::DSL
|
51
|
-
contract IdContract
|
52
|
-
|
53
|
-
include Call
|
54
|
-
end
|
55
|
-
|
56
|
-
# UT: subclasses contract.
|
57
|
-
it { Update["contract.default.class"].superclass.must_equal Update::IdContract }
|
58
|
-
# IT: only knows `id`.
|
59
|
-
it { Update.(id: 1, title: "Coaster")["model"].inspect.must_equal %{#<OpenStruct id=1>} }
|
60
|
-
|
61
|
-
# Op::contract with inheritance
|
62
|
-
# no ::contract call.
|
63
|
-
class Upgrade < Update
|
64
|
-
end
|
65
|
-
|
66
|
-
# UT: subclasses contract but doesn't share with parent.
|
67
|
-
it { Upgrade["contract.default.class"].superclass.must_equal Update::IdContract }
|
68
|
-
it { Upgrade["contract.default.class"].wont_equal Update["contract.default.class"] }
|
69
|
-
# IT: only knows `id`.
|
70
|
-
it { Upgrade.(id: 1, title: "Coaster")["model"].inspect.must_equal %{#<OpenStruct id=1>} }
|
71
|
-
|
72
|
-
# ::contract B overrides old A contract.
|
73
|
-
# this makes sure when calling contract(Constant), the old class gets wiped and is replaced with the new constant.
|
74
|
-
class Upsert < Update
|
75
|
-
class TitleContract < Reform::Form
|
76
|
-
property :title
|
77
|
-
end
|
78
|
-
|
79
|
-
contract TitleContract
|
80
|
-
end
|
81
|
-
|
82
|
-
# UT: subclasses contract.
|
83
|
-
it { Upsert["contract.default.class"].superclass.must_equal Upsert::TitleContract }
|
84
|
-
# IT: only knows `title`.
|
85
|
-
it { Upsert.(id: 1, title: "Coaster")["model"].inspect.must_equal %{#<OpenStruct title="Coaster">} }
|
86
|
-
|
87
|
-
# ::contract B do ..end overrides and extends new.
|
88
|
-
# using a constant will wipe out the existing class.
|
89
|
-
class Upside < Update
|
90
|
-
contract Upsert::TitleContract do
|
91
|
-
property :id
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
# UT: subclasses contract.
|
96
|
-
it { Upside["contract.default.class"].superclass.must_equal Upsert::TitleContract }
|
97
|
-
# IT: only knows `title`.
|
98
|
-
it { Upside.(id: 1, title: "Coaster")["model"].inspect.must_equal %{#<OpenStruct title="Coaster", id=1>} }
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
#---
|
103
|
-
# contract do .. end
|
104
|
-
# (with block)
|
105
|
-
class Delete < Trailblazer::Operation
|
106
|
-
include Call
|
107
|
-
extend Contract::DSL
|
108
|
-
contract do
|
109
|
-
property :title
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# UT: contract path is "contract.default.class"
|
114
|
-
it { Delete["contract.default.class"].definitions.keys.must_equal ["title"] }
|
115
|
-
# IT: knows `title`.
|
116
|
-
it { Delete.(id: 1, title: "Coaster")["model"].inspect.must_equal %{#<OpenStruct title=\"Coaster\">} }
|
117
|
-
|
118
|
-
class Wipe < Trailblazer::Operation
|
119
|
-
extend Contract::DSL
|
120
|
-
|
121
|
-
self["x"] = contract do end
|
122
|
-
end
|
123
|
-
# UT: ::contract returns form class
|
124
|
-
it { Wipe["x"].superclass.must_equal Reform::Form }
|
125
|
-
|
126
|
-
# subsequent calls merge.
|
127
|
-
class Remove < Trailblazer::Operation
|
128
|
-
extend Contract::DSL
|
129
|
-
include Call
|
130
|
-
|
131
|
-
contract do
|
132
|
-
property :title
|
133
|
-
end
|
134
|
-
|
135
|
-
contract do
|
136
|
-
property :id
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
# IT: knows `title` and `id`, since contracts get merged.
|
141
|
-
it { Remove.(id: 1, title: "Coaster")["model"].inspect.must_equal %{#<OpenStruct title=\"Coaster\", id=1>} }
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
# Operation::["contract.default.class"]
|
149
|
-
# Operation::["contract.default.class"]=
|
150
|
-
describe %{Operation::["contract.default.class"]} do
|
151
|
-
|
152
|
-
class Update2 < Trailblazer::Operation
|
153
|
-
self["contract.default.class"] = String
|
154
|
-
end
|
155
|
-
|
156
|
-
it { Update2["contract.default.class"].must_equal String }
|
157
|
-
end
|
158
|
-
|
159
|
-
describe "inheritance across operations" do
|
160
|
-
# inheritance
|
161
|
-
class Operation < Trailblazer::Operation
|
162
|
-
extend Contract::DSL
|
163
|
-
contract do
|
164
|
-
property :title
|
165
|
-
property :band
|
166
|
-
end
|
167
|
-
|
168
|
-
class JSON < self
|
169
|
-
contract do # inherit Contract
|
170
|
-
property :genre, validates: {presence: true}
|
171
|
-
property :band, virtual: true
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
class XML < self
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
# inherits subclassed Contract.
|
180
|
-
it { Operation["contract.default.class"].wont_equal Operation::JSON["contract.default.class"] }
|
181
|
-
it { Operation::XML["contract.default.class"].superclass.must_equal Reform::Form }
|
182
|
-
|
183
|
-
it do
|
184
|
-
form = Operation["contract.default.class"].new(OpenStruct.new)
|
185
|
-
form.validate({})#.must_equal true
|
186
|
-
form.errors.to_s.must_equal "{}"
|
187
|
-
|
188
|
-
form = Operation::JSON["contract.default.class"].new(OpenStruct.new)
|
189
|
-
form.validate({})#.must_equal true
|
190
|
-
form.errors.to_s.must_equal "{:genre=>[\"can't be blank\"]}"
|
191
|
-
end
|
192
|
-
|
193
|
-
# allows overriding options
|
194
|
-
it do
|
195
|
-
form = Operation::JSON["contract.default.class"].new(song = OpenStruct.new)
|
196
|
-
form.validate({genre: "Punkrock", band: "Osker"}).must_equal true
|
197
|
-
form.sync
|
198
|
-
|
199
|
-
song.genre.must_equal "Punkrock"
|
200
|
-
song.band.must_equal nil
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
describe "Op.contract CommentForm" do
|
205
|
-
class SongForm < Reform::Form
|
206
|
-
property :songTitle, validates: {presence: true}
|
207
|
-
end
|
208
|
-
|
209
|
-
class OpWithExternalContract < Trailblazer::Operation
|
210
|
-
extend Contract::DSL
|
211
|
-
contract SongForm
|
212
|
-
include Call
|
213
|
-
end
|
214
|
-
|
215
|
-
it { OpWithExternalContract.("songTitle"=> "Monsterparty")["contract.default"].songTitle.must_equal "Monsterparty" }
|
216
|
-
end
|
217
|
-
|
218
|
-
describe "Op.contract CommentForm do .. end" do
|
219
|
-
class DifferentSongForm < Reform::Form
|
220
|
-
property :songTitle, validates: {presence: true}
|
221
|
-
end
|
222
|
-
|
223
|
-
class OpNotExtendingContract < Trailblazer::Operation
|
224
|
-
extend Contract::DSL
|
225
|
-
contract DifferentSongForm
|
226
|
-
include Call
|
227
|
-
end
|
228
|
-
|
229
|
-
class OpExtendingContract < Trailblazer::Operation
|
230
|
-
extend Contract::DSL
|
231
|
-
contract DifferentSongForm do
|
232
|
-
property :genre
|
233
|
-
end
|
234
|
-
include Call
|
235
|
-
end
|
236
|
-
|
237
|
-
# this operation copies DifferentSongForm and shouldn't have `genre`.
|
238
|
-
it do
|
239
|
-
contract = OpNotExtendingContract.("songTitle"=>"Monsterparty", "genre"=>"Punk")["contract.default"]
|
240
|
-
contract.songTitle.must_equal "Monsterparty"
|
241
|
-
assert_raises(NoMethodError) { contract.genre }
|
242
|
-
end
|
243
|
-
|
244
|
-
# this operation copies DifferentSongForm and extends it with the property `genre`.
|
245
|
-
it do
|
246
|
-
contract = OpExtendingContract.("songTitle"=>"Monsterparty", "genre"=>"Punk")["contract.default"]
|
247
|
-
contract.songTitle.must_equal "Monsterparty"
|
248
|
-
contract.genre.must_equal "Punk"
|
249
|
-
end
|
250
|
-
|
251
|
-
# of course, the original contract wasn't modified, either.
|
252
|
-
it do
|
253
|
-
assert_raises(NoMethodError) { DifferentSongForm.new(OpenStruct.new).genre }
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
describe "Op.contract :name, Form" do
|
258
|
-
class Follow < Trailblazer::Operation
|
259
|
-
ParamsForm = Class.new
|
260
|
-
|
261
|
-
extend Contract::DSL
|
262
|
-
contract :params, ParamsForm
|
263
|
-
end
|
264
|
-
|
265
|
-
it { Follow["contract.params.class"].superclass.must_equal Follow::ParamsForm }
|
266
|
-
end
|
267
|
-
|
268
|
-
describe "Op.contract :name do..end" do
|
269
|
-
class Unfollow < Trailblazer::Operation
|
270
|
-
extend Contract::DSL
|
271
|
-
contract :params do
|
272
|
-
property :title
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
|
-
it { Unfollow["contract.params.class"].superclass.must_equal Reform::Form }
|
277
|
-
end
|
278
|
-
|
279
|
-
# multiple ::contract calls.
|
280
|
-
describe "multiple ::contract calls" do
|
281
|
-
class Star < Trailblazer::Operation
|
282
|
-
extend Contract::DSL
|
283
|
-
contract do
|
284
|
-
property :title
|
285
|
-
end
|
286
|
-
|
287
|
-
contract do
|
288
|
-
property :id
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
it { Star["contract.default.class"].definitions.keys.must_equal ["title", "id"] }
|
293
|
-
end
|
294
|
-
end
|
@@ -1,169 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
require "representable/json"
|
3
|
-
require "trailblazer/operation/representer"
|
4
|
-
require "trailblazer/operation/contract"
|
5
|
-
|
6
|
-
class DslRepresenterTest < MiniTest::Spec
|
7
|
-
module SongProcess
|
8
|
-
def process(params)
|
9
|
-
self["model"] = OpenStruct.new(params)
|
10
|
-
end
|
11
|
-
|
12
|
-
def represented
|
13
|
-
self["model"]
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
describe "inheritance across operations" do
|
18
|
-
class Operation < Trailblazer::Operation
|
19
|
-
include Representer
|
20
|
-
include SongProcess
|
21
|
-
|
22
|
-
representer do
|
23
|
-
property :title
|
24
|
-
end
|
25
|
-
|
26
|
-
class JSON < self
|
27
|
-
representer do
|
28
|
-
property :band
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
it { Operation.(title: "Nothing To Lose", band: "Gary Moore").to_json.must_equal %{{"title":"Nothing To Lose"}} }
|
34
|
-
# only the subclass must have the `band` field, even though it's set in the original operation.
|
35
|
-
it { Operation::JSON.(title: "Nothing To Lose", band: "Gary Moore").to_json.must_equal %{{"title":"Nothing To Lose","band":"Gary Moore"}} }
|
36
|
-
end
|
37
|
-
|
38
|
-
describe "Op.representer CommentRepresenter" do
|
39
|
-
class SongRepresenter < Representable::Decorator
|
40
|
-
include Representable::JSON
|
41
|
-
property :songTitle
|
42
|
-
end
|
43
|
-
|
44
|
-
class OpWithExternalRepresenter < Trailblazer::Operation
|
45
|
-
include Representer
|
46
|
-
include SongProcess
|
47
|
-
representer SongRepresenter
|
48
|
-
end
|
49
|
-
|
50
|
-
it { OpWithExternalRepresenter.("songTitle"=>"Listen To Your Heartbeat").to_json.must_equal %{{"songTitle":"Listen To Your Heartbeat"}} }
|
51
|
-
end
|
52
|
-
|
53
|
-
# name for representer
|
54
|
-
describe "1) Op.representer :parse, Representer" do
|
55
|
-
class Op1 < Trailblazer::Operation
|
56
|
-
include Representer
|
57
|
-
representer :parse, String
|
58
|
-
end
|
59
|
-
|
60
|
-
it { Op1["representer.parse.class"].superclass.must_equal String }
|
61
|
-
it { Op1.({})["representer.parse.class"].superclass.must_equal String }
|
62
|
-
end
|
63
|
-
|
64
|
-
# name for default representer
|
65
|
-
describe "2) Op.representer Representer" do
|
66
|
-
class Op2 < Trailblazer::Operation
|
67
|
-
include Representer
|
68
|
-
representer String
|
69
|
-
def call(*); self; end
|
70
|
-
end
|
71
|
-
|
72
|
-
it { Op2["representer.default.class"].superclass.must_equal String }
|
73
|
-
it { Op2.({})["representer.default.class"].superclass.must_equal String }
|
74
|
-
it { Op2.({}, "representer.default.class" => Integer)["representer.default.class"].must_equal Integer }
|
75
|
-
end
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
describe "Op.representer CommentRepresenter do .. end" do
|
80
|
-
class HitRepresenter < Representable::Decorator
|
81
|
-
include Representable::JSON
|
82
|
-
property :title
|
83
|
-
end
|
84
|
-
|
85
|
-
class OpNotExtendingRepresenter < Trailblazer::Operation
|
86
|
-
include Representer
|
87
|
-
include SongProcess
|
88
|
-
representer HitRepresenter
|
89
|
-
end
|
90
|
-
|
91
|
-
class OpExtendingRepresenter < Trailblazer::Operation
|
92
|
-
include Representer
|
93
|
-
include SongProcess
|
94
|
-
representer HitRepresenter do
|
95
|
-
property :genre
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# this operation copies HitRepresenter and shouldn't have `genre`.
|
100
|
-
it do
|
101
|
-
OpNotExtendingRepresenter.("title"=>"Monsterparty", "genre"=>"Punk").to_json.must_equal %{{"title":"Monsterparty"}}
|
102
|
-
end
|
103
|
-
|
104
|
-
# # this operation copies HitRepresenter and extends it with the property `genre`.
|
105
|
-
it do
|
106
|
-
OpExtendingRepresenter.("title"=>"Monsterparty", "genre"=>"Punk").to_json.must_equal %{{"title":"Monsterparty","genre":"Punk"}}
|
107
|
-
end
|
108
|
-
|
109
|
-
# # of course, the original representer wasn't modified, either.
|
110
|
-
it do
|
111
|
-
HitRepresenter.new(OpenStruct.new(title: "Monsterparty", genre: "Punk")).to_json.must_equal %{{"title":"Monsterparty"}}
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
describe "Op.representer (inferring)" do
|
116
|
-
class ContractOperation < Trailblazer::Operation
|
117
|
-
include Representer
|
118
|
-
include Representer::InferFromContract
|
119
|
-
include SongProcess
|
120
|
-
include Contract::Explicit
|
121
|
-
|
122
|
-
contract do
|
123
|
-
property :songTitle
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
class ContractOperation2 < Trailblazer::Operation
|
128
|
-
include Representer
|
129
|
-
include SongProcess
|
130
|
-
include Contract::Explicit
|
131
|
-
include Representer::InferFromContract
|
132
|
-
contract ContractOperation["contract.default.class"]
|
133
|
-
|
134
|
-
representer do
|
135
|
-
property :genre
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
it { ContractOperation.("songTitle"=>"Monsterparty", "genre"=>"Punk").to_json.must_equal %{{"songTitle":"Monsterparty"}} }
|
140
|
-
# this representer block extends the inferred from contract.
|
141
|
-
it { ContractOperation2.("songTitle"=>"Monsterparty", "genre"=>"Punk").to_json.must_equal %{{"songTitle":"Monsterparty","genre":"Punk"}} }
|
142
|
-
end
|
143
|
-
|
144
|
-
describe "Op.representer_class" do
|
145
|
-
class PlayRepresenter < Representable::Decorator
|
146
|
-
include Representable::JSON
|
147
|
-
property :title
|
148
|
-
end
|
149
|
-
|
150
|
-
class OpSettingRepresenter < Trailblazer::Operation
|
151
|
-
include Representer
|
152
|
-
include SongProcess
|
153
|
-
self["representer.default.class"] = PlayRepresenter
|
154
|
-
end
|
155
|
-
|
156
|
-
class OpExtendRepresenter < Trailblazer::Operation
|
157
|
-
include Representer
|
158
|
-
include SongProcess
|
159
|
-
self["representer.default.class"] = PlayRepresenter
|
160
|
-
representer do
|
161
|
-
property :genre
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
# both operations produce the same as the representer is shared, not copied.
|
166
|
-
it { skip; OpSettingRepresenter.("title"=>"Monsterparty", "genre"=>"Punk").to_json.must_equal %{{"title":"Monsterparty","genre":"Punk"}} }
|
167
|
-
it { OpExtendRepresenter.("title"=>"Monsterparty", "genre"=>"Punk").to_json.must_equal %{{"title":"Monsterparty","genre":"Punk"}} }
|
168
|
-
end
|
169
|
-
end
|