trailblazer 1.1.1 → 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 -7
- data/CHANGES.md +224 -0
- data/COMM-LICENSE +62 -0
- data/CONTRIBUTING.md +179 -0
- data/Gemfile +0 -10
- data/LICENSE +9 -0
- data/README.md +68 -189
- data/Rakefile +3 -3
- data/lib/trailblazer/version.rb +3 -1
- data/lib/trailblazer.rb +3 -6
- data/test/test_helper.rb +32 -3
- data/trailblazer.gemspec +11 -15
- metadata +28 -132
- data/LICENSE.txt +0 -22
- data/TODO.md +0 -11
- data/doc/Trb-The-Stack.png +0 -0
- data/doc/trb.jpg +0 -0
- 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/builder.rb +0 -26
- data/lib/trailblazer/operation/callback.rb +0 -53
- data/lib/trailblazer/operation/collection.rb +0 -6
- data/lib/trailblazer/operation/controller.rb +0 -72
- 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/model.rb +0 -50
- data/lib/trailblazer/operation/module.rb +0 -29
- data/lib/trailblazer/operation/policy/guard.rb +0 -35
- data/lib/trailblazer/operation/policy.rb +0 -85
- data/lib/trailblazer/operation/representer.rb +0 -98
- data/lib/trailblazer/operation/resolver.rb +0 -30
- data/lib/trailblazer/operation/uploaded_file.rb +0 -77
- data/lib/trailblazer/operation.rb +0 -175
- data/test/callback_test.rb +0 -104
- data/test/collection_test.rb +0 -57
- data/test/model_test.rb +0 -148
- data/test/module_test.rb +0 -93
- data/test/operation/builder_test.rb +0 -41
- data/test/operation/contract_test.rb +0 -30
- data/test/operation/controller_test.rb +0 -111
- data/test/operation/dsl/callback_test.rb +0 -118
- data/test/operation/dsl/contract_test.rb +0 -104
- data/test/operation/dsl/representer_test.rb +0 -142
- data/test/operation/external_model_test.rb +0 -71
- data/test/operation/guard_test.rb +0 -152
- data/test/operation/policy_test.rb +0 -97
- data/test/operation/reject_test.rb +0 -34
- data/test/operation/resolver_test.rb +0 -83
- data/test/operation_test.rb +0 -275
- data/test/representer_test.rb +0 -238
- data/test/rollback_test.rb +0 -47
data/test/callback_test.rb
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require "trailblazer/operation/callback"
|
3
|
-
|
4
|
-
# callbacks are tested in Disposable::Callback::Group.
|
5
|
-
class OperationCallbackTest < MiniTest::Spec
|
6
|
-
Song = Struct.new(:name)
|
7
|
-
|
8
|
-
class Create < Trailblazer::Operation
|
9
|
-
include Trailblazer::Operation::Callback
|
10
|
-
|
11
|
-
contract do
|
12
|
-
property :name
|
13
|
-
end
|
14
|
-
|
15
|
-
callback do
|
16
|
-
on_change :notify_me!
|
17
|
-
on_change :notify_you!
|
18
|
-
end
|
19
|
-
|
20
|
-
# TODO: always dispatch, pass params.
|
21
|
-
|
22
|
-
def process(params)
|
23
|
-
@model = Song.new
|
24
|
-
|
25
|
-
validate(params, @model) do
|
26
|
-
callback!
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def dispatched
|
31
|
-
@dispatched ||= []
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
def notify_me!(*)
|
36
|
-
dispatched << :notify_me!
|
37
|
-
end
|
38
|
-
|
39
|
-
def notify_you!(*)
|
40
|
-
dispatched << :notify_you!
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
class Update < Create
|
46
|
-
# TODO: allow skipping groups.
|
47
|
-
# skip_dispatch :notify_me!
|
48
|
-
|
49
|
-
callback do
|
50
|
-
remove! :on_change, :notify_me!
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
it "invokes all callbacks" do
|
56
|
-
op = Create.({"name"=>"Keep On Running"})
|
57
|
-
op.dispatched.must_equal [:notify_me!, :notify_you!]
|
58
|
-
end
|
59
|
-
|
60
|
-
it "does not invoke removed callbacks" do
|
61
|
-
op = Update.({"name"=>"Keep On Running"})
|
62
|
-
op.dispatched.must_equal [:notify_you!]
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# TODO: remove in 1.2.
|
67
|
-
require "trailblazer/operation/dispatch"
|
68
|
-
class OperationDeprecatedDispatchTest < MiniTest::Spec
|
69
|
-
Song = Struct.new(:name)
|
70
|
-
|
71
|
-
class Create < Trailblazer::Operation
|
72
|
-
include Trailblazer::Operation::Dispatch
|
73
|
-
|
74
|
-
contract do
|
75
|
-
property :name
|
76
|
-
end
|
77
|
-
|
78
|
-
callback do
|
79
|
-
on_change :notify_me!
|
80
|
-
end
|
81
|
-
|
82
|
-
def process(params)
|
83
|
-
@model = Song.new
|
84
|
-
|
85
|
-
validate(params, @model) do
|
86
|
-
dispatch!
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
def dispatched
|
91
|
-
@dispatched ||= []
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
def notify_me!(*)
|
96
|
-
dispatched << :notify_me!
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
it "invokes all callbacks [deprecated]" do
|
101
|
-
op = Create.({"name"=>"Keep On Running"})
|
102
|
-
op.dispatched.must_equal [:notify_me!]
|
103
|
-
end
|
104
|
-
end
|
data/test/collection_test.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
require "trailblazer/operation/collection"
|
3
|
-
require "trailblazer/operation/model"
|
4
|
-
|
5
|
-
class CollectionTest < MiniTest::Spec
|
6
|
-
Song = Struct.new(:title, :id) do
|
7
|
-
class << self
|
8
|
-
attr_accessor :all_records
|
9
|
-
|
10
|
-
def all
|
11
|
-
all_records
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
|
-
class CreateOperation < Trailblazer::Operation
|
18
|
-
include Model
|
19
|
-
model Song
|
20
|
-
action :create
|
21
|
-
|
22
|
-
contract do
|
23
|
-
property :title
|
24
|
-
validates :title, presence: true
|
25
|
-
end
|
26
|
-
|
27
|
-
def process(params)
|
28
|
-
validate(params[:song]) do |f|
|
29
|
-
f.sync
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class FetchCollectionOperation < CreateOperation
|
35
|
-
include Trailblazer::Operation::Collection
|
36
|
-
|
37
|
-
model Song
|
38
|
-
|
39
|
-
contract do
|
40
|
-
property :title
|
41
|
-
end
|
42
|
-
|
43
|
-
def model!(params)
|
44
|
-
Song.all
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# ::present.
|
49
|
-
it do
|
50
|
-
Song.all_records = [
|
51
|
-
CreateOperation.(song: {title: "Blue Rondo a la Turk"}).model,
|
52
|
-
CreateOperation.(song: {title: "Mercy Day For Mr. Vengeance"}).model
|
53
|
-
]
|
54
|
-
op = FetchCollectionOperation.present(user_id: 0)
|
55
|
-
op.model.must_equal Song.all_records
|
56
|
-
end
|
57
|
-
end
|
data/test/model_test.rb
DELETED
@@ -1,148 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'trailblazer/operation'
|
3
|
-
|
4
|
-
class ModelTest < MiniTest::Spec
|
5
|
-
Song = Struct.new(:title, :id) do
|
6
|
-
class << self
|
7
|
-
attr_accessor :find_result # TODO: eventually, replace with AR test.
|
8
|
-
attr_accessor :all_records
|
9
|
-
|
10
|
-
def find(id)
|
11
|
-
find_result
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
class CreateOperation < Trailblazer::Operation
|
17
|
-
include Model
|
18
|
-
model Song
|
19
|
-
action :create
|
20
|
-
|
21
|
-
contract do
|
22
|
-
property :title
|
23
|
-
validates :title, presence: true
|
24
|
-
end
|
25
|
-
|
26
|
-
def process(params)
|
27
|
-
validate(params[:song]) do |f|
|
28
|
-
f.sync
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
|
-
# creates model for you.
|
35
|
-
it { CreateOperation.(song: {title: "Blue Rondo a la Turk"}).model.title.must_equal "Blue Rondo a la Turk" }
|
36
|
-
# exposes #model.
|
37
|
-
it { CreateOperation.(song: {title: "Blue Rondo a la Turk"}).model.must_be_instance_of Song }
|
38
|
-
|
39
|
-
class ModifyingCreateOperation < CreateOperation
|
40
|
-
def process(params)
|
41
|
-
model.instance_eval { def genre; "Punkrock"; end }
|
42
|
-
|
43
|
-
validate(params[:song]) do |f|
|
44
|
-
f.sync
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# lets you modify model.
|
50
|
-
it { ModifyingCreateOperation.(song: {title: "Blue Rondo a la Turk"}).model.title.must_equal "Blue Rondo a la Turk" }
|
51
|
-
it { ModifyingCreateOperation.(song: {title: "Blue Rondo a la Turk"}).model.genre.must_equal "Punkrock" }
|
52
|
-
|
53
|
-
# Update
|
54
|
-
class UpdateOperation < CreateOperation
|
55
|
-
action :update
|
56
|
-
end
|
57
|
-
|
58
|
-
# finds model and updates.
|
59
|
-
it do
|
60
|
-
song = CreateOperation.(song: {title: "Anchor End"}).model
|
61
|
-
Song.find_result = song
|
62
|
-
|
63
|
-
UpdateOperation.(id: song.id, song: {title: "The Rip"}).model.title.must_equal "The Rip"
|
64
|
-
song.title.must_equal "The Rip"
|
65
|
-
end
|
66
|
-
|
67
|
-
# Find == Update
|
68
|
-
class FindOperation < CreateOperation
|
69
|
-
action :find
|
70
|
-
end
|
71
|
-
|
72
|
-
# finds model and updates.
|
73
|
-
it do
|
74
|
-
song = CreateOperation.(song: {title: "Anchor End"}).model
|
75
|
-
Song.find_result = song
|
76
|
-
|
77
|
-
FindOperation.(id: song.id, song: {title: "The Rip"}).model.title.must_equal "The Rip"
|
78
|
-
song.title.must_equal "The Rip"
|
79
|
-
end
|
80
|
-
|
81
|
-
|
82
|
-
class DefaultCreateOperation < Trailblazer::Operation
|
83
|
-
include Model
|
84
|
-
model Song
|
85
|
-
|
86
|
-
def process(params)
|
87
|
-
self
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
# uses :create as default if not set via ::action.
|
92
|
-
it { DefaultCreateOperation.({}).model.must_equal Song.new }
|
93
|
-
|
94
|
-
# model Song, :action
|
95
|
-
class ModelUpdateOperation < CreateOperation
|
96
|
-
model Song, :update
|
97
|
-
end
|
98
|
-
|
99
|
-
# allows ::model, :action.
|
100
|
-
it do
|
101
|
-
Song.find_result = song = Song.new
|
102
|
-
ModelUpdateOperation.({id: 1, song: {title: "Mercy Day For Mr. Vengeance"}}).model.must_equal song
|
103
|
-
end
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
# Op#setup_model!
|
108
|
-
class SetupModelOperation < CreateOperation
|
109
|
-
def setup_model!(params)
|
110
|
-
model.instance_eval { @params = params; def params; @params.to_s; end }
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
it { SetupModelOperation.(song: {title: "Emily Kane"}).model.params.must_equal "{:song=>{:title=>\"Emily Kane\"}}" }
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
# no call to ::model raises error.
|
119
|
-
class NoModelOperation < Trailblazer::Operation
|
120
|
-
include Model
|
121
|
-
|
122
|
-
def process(params)
|
123
|
-
self
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
# uses :create as default if not set via ::action.
|
128
|
-
it { assert_raises(RuntimeError){ NoModelOperation.({}) } }
|
129
|
-
|
130
|
-
# allow passing validate(params, model, contract_class)
|
131
|
-
class OperationWithPrivateContract < Trailblazer::Operation
|
132
|
-
include Model
|
133
|
-
model Song
|
134
|
-
|
135
|
-
class Contract < Reform::Form
|
136
|
-
property :title
|
137
|
-
end
|
138
|
-
|
139
|
-
def process(params)
|
140
|
-
validate(params[:song], model, Contract) do |f|
|
141
|
-
f.sync
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
# uses private Contract class.
|
147
|
-
it { OperationWithPrivateContract.(song: {title: "Blue Rondo a la Turk"}).model.title.must_equal "Blue Rondo a la Turk" }
|
148
|
-
end
|
data/test/module_test.rb
DELETED
@@ -1,93 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require "trailblazer/operation/module"
|
3
|
-
require "trailblazer/operation/dispatch"
|
4
|
-
|
5
|
-
class OperationModuleTest < MiniTest::Spec
|
6
|
-
Song = Struct.new(:name, :artist)
|
7
|
-
Artist = Struct.new(:id, :full_name)
|
8
|
-
|
9
|
-
class Create < Trailblazer::Operation
|
10
|
-
include Trailblazer::Operation::Dispatch
|
11
|
-
|
12
|
-
contract do
|
13
|
-
property :name
|
14
|
-
property :artist, populate_if_empty: Artist do
|
15
|
-
property :id
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
callback do
|
20
|
-
on_change :notify_me!
|
21
|
-
end
|
22
|
-
|
23
|
-
def process(params)
|
24
|
-
@model = Song.new
|
25
|
-
|
26
|
-
validate(params, @model) do
|
27
|
-
contract.sync
|
28
|
-
|
29
|
-
dispatch!
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def dispatched
|
34
|
-
@dispatched ||= []
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
def notify_me!(*)
|
39
|
-
dispatched << :notify_me!
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
module SignedIn
|
45
|
-
include Trailblazer::Operation::Module
|
46
|
-
|
47
|
-
contract do
|
48
|
-
property :artist, inherit: true do
|
49
|
-
property :full_name
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
callback do
|
54
|
-
on_change :notify_you!
|
55
|
-
end
|
56
|
-
|
57
|
-
def notify_you!(*)
|
58
|
-
dispatched << :notify_you!
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
class Update < Create
|
64
|
-
callback do
|
65
|
-
on_change :notify_them!
|
66
|
-
end
|
67
|
-
|
68
|
-
include SignedIn
|
69
|
-
|
70
|
-
def notify_them!(*)
|
71
|
-
dispatched << :notify_them!
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
|
76
|
-
it do
|
77
|
-
op = Create.({name: "Feelings", artist: {id: 1, full_name: "The Offspring"}})
|
78
|
-
|
79
|
-
op.dispatched.must_equal [:notify_me!]
|
80
|
-
op.model.name.must_equal "Feelings"
|
81
|
-
op.model.artist.id.must_equal 1
|
82
|
-
op.model.artist.full_name.must_equal nil # property not declared.
|
83
|
-
end
|
84
|
-
|
85
|
-
it do
|
86
|
-
op = Update.({name: "Feelings", artist: {id: 1, full_name: "The Offspring"}})
|
87
|
-
|
88
|
-
op.dispatched.must_equal [:notify_me!, :notify_them!, :notify_you!]
|
89
|
-
op.model.name.must_equal "Feelings"
|
90
|
-
op.model.artist.id.must_equal 1
|
91
|
-
op.model.artist.full_name.must_equal "The Offspring" # property declared via Module.
|
92
|
-
end
|
93
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class OperationBuilderTest < MiniTest::Spec
|
4
|
-
class ParentOperation < Trailblazer::Operation
|
5
|
-
def process(params)
|
6
|
-
end
|
7
|
-
|
8
|
-
class Sub < self
|
9
|
-
end
|
10
|
-
|
11
|
-
builds do |params|
|
12
|
-
Sub if params[:sub]
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
it { ParentOperation.run({}).last.class.must_equal ParentOperation }
|
17
|
-
it { ParentOperation.run({sub: true}).last.class.must_equal ParentOperation::Sub }
|
18
|
-
it { ParentOperation.({}).class.must_equal ParentOperation }
|
19
|
-
it { ParentOperation.({sub: true}).class.must_equal ParentOperation::Sub }
|
20
|
-
end
|
21
|
-
|
22
|
-
class OperationBuilderClassTest < MiniTest::Spec
|
23
|
-
class SuperOperation < Trailblazer::Operation
|
24
|
-
builds do |params|
|
25
|
-
self::Sub if params[:sub] # Sub is defined in ParentOperation.
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
class ParentOperation < Trailblazer::Operation
|
30
|
-
def process(params)
|
31
|
-
end
|
32
|
-
|
33
|
-
class Sub < self
|
34
|
-
end
|
35
|
-
|
36
|
-
self.builder_class = SuperOperation.builder_class
|
37
|
-
end
|
38
|
-
|
39
|
-
it { ParentOperation.({}).class.must_equal ParentOperation }
|
40
|
-
it { ParentOperation.({sub: true}).class.must_equal ParentOperation::Sub }
|
41
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
|
4
|
-
class OperationContractTest < MiniTest::Spec
|
5
|
-
|
6
|
-
class Operation < Trailblazer::Operation
|
7
|
-
contract do
|
8
|
-
property :id
|
9
|
-
property :title
|
10
|
-
property :length
|
11
|
-
end
|
12
|
-
|
13
|
-
def process(params)
|
14
|
-
@model = Struct.new(:id, :title, :length).new
|
15
|
-
|
16
|
-
contract.id = 1
|
17
|
-
validate(params) do
|
18
|
-
contract.length = 3
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# allow using #contract before #validate.
|
24
|
-
it do
|
25
|
-
op = Operation.(title: "Beethoven")
|
26
|
-
op.contract.id.must_equal 1
|
27
|
-
op.contract.title.must_equal "Beethoven"
|
28
|
-
op.contract.length.must_equal 3
|
29
|
-
end
|
30
|
-
end
|
@@ -1,111 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
require "trailblazer/operation/controller"
|
3
|
-
|
4
|
-
class ControllerTest < Minitest::Spec
|
5
|
-
def self.controller!(&block)
|
6
|
-
let (:_controller) {
|
7
|
-
Class.new do
|
8
|
-
include Trailblazer::Operation::Controller
|
9
|
-
|
10
|
-
def initialize(params={})
|
11
|
-
@params = params
|
12
|
-
end
|
13
|
-
attr_reader :params, :request
|
14
|
-
|
15
|
-
class_eval(&block)
|
16
|
-
self
|
17
|
-
end
|
18
|
-
}
|
19
|
-
end
|
20
|
-
|
21
|
-
def controller(params={})
|
22
|
-
_controller.new(params)
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
|
-
User = Struct.new(:role)
|
27
|
-
|
28
|
-
Comment = Struct.new(:body)
|
29
|
-
|
30
|
-
class Comment::Update < Trailblazer::Operation
|
31
|
-
def model!(params)
|
32
|
-
Comment.new(params[:body])
|
33
|
-
end
|
34
|
-
|
35
|
-
def inspect
|
36
|
-
super.sub(/:0x\w+/, "")
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
|
41
|
-
describe "#present with options" do
|
42
|
-
controller! do
|
43
|
-
def show
|
44
|
-
present Comment::Update, params: { current_user: User.new(:admin) }
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
it do
|
49
|
-
controller.show.inspect.must_equal "#<ControllerTest::Comment::Update @options={}, @valid=true, @params={:current_user=>#<struct ControllerTest::User role=:admin>}, @model=#<struct ControllerTest::Comment body=nil>>"
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "#params!" do
|
54
|
-
controller! do
|
55
|
-
def show
|
56
|
-
present Comment::Update, params: "Cool!"
|
57
|
-
end
|
58
|
-
|
59
|
-
def params!(params)
|
60
|
-
{ body: params }
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
it { controller.show.inspect.must_equal "#<ControllerTest::Comment::Update @options={}, @valid=true, @params={:body=>\"Cool!\"}, @model=#<struct ControllerTest::Comment body=\"Cool!\">>" }
|
65
|
-
end
|
66
|
-
|
67
|
-
describe "#form" do
|
68
|
-
class Comment::Create < Trailblazer::Operation
|
69
|
-
def model!(params)
|
70
|
-
Comment.new
|
71
|
-
end
|
72
|
-
|
73
|
-
contract do
|
74
|
-
def prepopulate!(options)
|
75
|
-
@options = options
|
76
|
-
end
|
77
|
-
attr_reader :options
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
describe "#prepopulate! options" do
|
82
|
-
controller! do
|
83
|
-
def show
|
84
|
-
form Comment::Create
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
it { controller(__body: "Great!").show.options.inspect.must_equal "{:params=>{:__body=>\"Great!\"}}" }
|
89
|
-
end
|
90
|
-
|
91
|
-
describe "with additional options" do
|
92
|
-
controller! do
|
93
|
-
def show
|
94
|
-
form Comment::Create, admin: true
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
it { controller(__body: "Great!").show.options.inspect.must_equal "{:admin=>true, :params=>{:__body=>\"Great!\"}}" }
|
99
|
-
end
|
100
|
-
|
101
|
-
describe "with options and :params" do
|
102
|
-
controller! do
|
103
|
-
def show
|
104
|
-
form Comment::Create, admin: true, params: params.merge(user: User.new)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
it { controller(__body: "Great!").show.options.inspect.must_equal "{:admin=>true, :params=>{:__body=>\"Great!\", :user=>#<struct ControllerTest::User role=nil>}}" }
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
@@ -1,118 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
require "trailblazer/operation/dispatch"
|
3
|
-
|
4
|
-
|
5
|
-
class DslCallbackTest < MiniTest::Spec
|
6
|
-
module SongProcess
|
7
|
-
def process(params)
|
8
|
-
contract(OpenStruct.new).validate(params)
|
9
|
-
dispatch!
|
10
|
-
end
|
11
|
-
|
12
|
-
def _invocations
|
13
|
-
@_invocations ||= []
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.included(includer)
|
17
|
-
includer.contract do
|
18
|
-
property :title
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe "inheritance across operations" do
|
24
|
-
class Operation < Trailblazer::Operation
|
25
|
-
include Dispatch
|
26
|
-
include SongProcess
|
27
|
-
|
28
|
-
callback do
|
29
|
-
on_change :default!
|
30
|
-
end
|
31
|
-
|
32
|
-
class Admin < self
|
33
|
-
callback do
|
34
|
-
on_change :admin_default!
|
35
|
-
end
|
36
|
-
|
37
|
-
callback(:after_save) { on_change :after_save! }
|
38
|
-
|
39
|
-
def admin_default!(*); _invocations << :admin_default!; end
|
40
|
-
def after_save!(*); _invocations << :after_save!; end
|
41
|
-
|
42
|
-
def process(*)
|
43
|
-
super
|
44
|
-
dispatch!(:after_save)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def default!(*); _invocations << :default!; end
|
49
|
-
end
|
50
|
-
|
51
|
-
it { Operation.({"title"=> "Love-less"})._invocations.must_equal([:default!]) }
|
52
|
-
it { Operation::Admin.({"title"=> "Love-less"})._invocations.must_equal([:default!, :admin_default!, :after_save!]) }
|
53
|
-
end
|
54
|
-
|
55
|
-
describe "Op.callback" do
|
56
|
-
it { Operation.callback(:default).must_equal Operation.callbacks[:default][:group] }
|
57
|
-
end
|
58
|
-
|
59
|
-
describe "Op.callback :after_save, AfterSaveCallback" do
|
60
|
-
class AfterSaveCallback < Disposable::Callback::Group
|
61
|
-
on_change :after_save!
|
62
|
-
|
63
|
-
def after_save!(twin, options)
|
64
|
-
options[:operation]._invocations << :after_save!
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
class OpWithExternalCallback < Trailblazer::Operation
|
69
|
-
include Dispatch
|
70
|
-
include SongProcess
|
71
|
-
callback :after_save, AfterSaveCallback
|
72
|
-
|
73
|
-
def process(params)
|
74
|
-
contract(OpenStruct.new).validate(params)
|
75
|
-
dispatch!(:after_save)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
it { OpWithExternalCallback.("title"=>"Thunder Rising")._invocations.must_equal([:after_save!]) }
|
80
|
-
end
|
81
|
-
|
82
|
-
describe "Op.callback :after_save, AfterSaveCallback do .. end" do
|
83
|
-
class DefaultCallback < Disposable::Callback::Group
|
84
|
-
on_change :default!
|
85
|
-
|
86
|
-
def default!(twin, options)
|
87
|
-
options[:operation]._invocations << :default!
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
class OpUsingCallback < Trailblazer::Operation
|
92
|
-
include Dispatch
|
93
|
-
include SongProcess
|
94
|
-
callback :default, DefaultCallback
|
95
|
-
end
|
96
|
-
|
97
|
-
class OpExtendingCallback < Trailblazer::Operation
|
98
|
-
include Dispatch
|
99
|
-
include SongProcess
|
100
|
-
callback :default, DefaultCallback do
|
101
|
-
on_change :after_save!
|
102
|
-
|
103
|
-
def default!(twin, options)
|
104
|
-
options[:operation]._invocations << :extended_default!
|
105
|
-
end
|
106
|
-
|
107
|
-
def after_save!(twin, options)
|
108
|
-
options[:operation]._invocations << :after_save!
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# this operation copies DefaultCallback and shouldn't run #after_save!.
|
114
|
-
it { OpUsingCallback.(title: "Thunder Rising")._invocations.must_equal([:default!]) }
|
115
|
-
# this operation copies DefaultCallback, extends it and runs #after_save!.
|
116
|
-
it { OpExtendingCallback.(title: "Thunder Rising")._invocations.must_equal([:extended_default!, :after_save!]) }
|
117
|
-
end
|
118
|
-
end
|