trailblazer 2.0.0 → 2.0.1
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/CHANGES.md +13 -0
- data/COMM-LICENSE +21 -21
- data/Gemfile +3 -0
- data/README.md +15 -77
- data/Rakefile +1 -2
- data/doc/operation-2017.png +0 -0
- data/lib/trailblazer.rb +0 -1
- data/lib/trailblazer/operation/callback.rb +10 -19
- data/lib/trailblazer/operation/contract.rb +7 -8
- data/lib/trailblazer/operation/guard.rb +4 -13
- data/lib/trailblazer/operation/model.rb +30 -32
- data/lib/trailblazer/operation/nested.rb +21 -32
- data/lib/trailblazer/operation/persist.rb +4 -8
- data/lib/trailblazer/operation/policy.rb +5 -15
- data/lib/trailblazer/operation/pundit.rb +8 -17
- data/lib/trailblazer/operation/rescue.rb +17 -17
- data/lib/trailblazer/operation/validate.rb +34 -21
- data/lib/trailblazer/operation/wrap.rb +12 -25
- data/lib/trailblazer/version.rb +1 -1
- data/test/docs/dry_test.rb +4 -4
- data/test/docs/fast_test.rb +164 -0
- data/test/docs/guard_test.rb +2 -2
- data/test/docs/macro_test.rb +36 -0
- data/test/docs/model_test.rb +52 -0
- data/test/docs/nested_test.rb +101 -4
- data/test/docs/operation_test.rb +225 -1
- data/test/docs/pundit_test.rb +18 -17
- data/test/docs/rescue_test.rb +3 -3
- data/test/docs/wrap_test.rb +1 -0
- data/test/operation/callback_test.rb +5 -5
- data/test/operation/contract_test.rb +30 -19
- data/test/operation/dsl/callback_test.rb +2 -2
- data/test/operation/dsl/contract_test.rb +4 -4
- data/test/operation/model_test.rb +12 -57
- data/test/operation/persist_test.rb +7 -7
- data/test/operation/pipedream_test.rb +9 -9
- data/test/operation/pipetree_test.rb +5 -5
- data/test/operation/pundit_test.rb +7 -7
- data/test/operation/resolver_test.rb +47 -47
- data/trailblazer.gemspec +1 -1
- metadata +18 -11
- data/lib/trailblazer/operation/builder.rb +0 -24
- data/lib/trailblazer/operation/resolver.rb +0 -22
- data/test/controller_test.rb +0 -115
- data/test/operation/builder_test.rb +0 -89
@@ -17,8 +17,8 @@ class PolicyTest < Minitest::Spec
|
|
17
17
|
#---
|
18
18
|
# Instance-level: Only policy, no model
|
19
19
|
class Create < Trailblazer::Operation
|
20
|
-
|
21
|
-
|
20
|
+
step Policy::Pundit( Auth, :only_user? )
|
21
|
+
step :process
|
22
22
|
|
23
23
|
def process(*)
|
24
24
|
self["process"] = true
|
@@ -50,10 +50,10 @@ class PolicyTest < Minitest::Spec
|
|
50
50
|
#---
|
51
51
|
# inheritance, adding Model
|
52
52
|
class Show < Create
|
53
|
-
|
53
|
+
step Model( Song, :new ), before: "policy.default.eval"
|
54
54
|
end
|
55
55
|
|
56
|
-
it { Show["pipetree"].inspect.must_equal %{[
|
56
|
+
it { Show["pipetree"].inspect.must_equal %{[>operation.new,>model.build,>policy.default.eval,>process]} }
|
57
57
|
|
58
58
|
# invalid because user AND model.
|
59
59
|
it do
|
@@ -75,9 +75,9 @@ class PolicyTest < Minitest::Spec
|
|
75
75
|
##--
|
76
76
|
# TOOOODOOO: Policy and Model before Build ("External" or almost Resolver)
|
77
77
|
class Edit < Trailblazer::Operation
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
step Model Song, :find
|
79
|
+
step Policy::Pundit( Auth, :user_and_model? )
|
80
|
+
step :process
|
81
81
|
|
82
82
|
def process(*); self["process"] = true end
|
83
83
|
end
|
@@ -1,47 +1,47 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class ResolverTest < Minitest::Spec
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
1
|
+
# require "test_helper"
|
2
|
+
|
3
|
+
# class ResolverTest < Minitest::Spec
|
4
|
+
# Song = Struct.new(:id) do
|
5
|
+
# def self.find(id); new(id) end
|
6
|
+
# end
|
7
|
+
|
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
|
15
|
+
|
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
|
+
# }
|
23
|
+
|
24
|
+
# step Model( Song, :update ), before: "operation.new"
|
25
|
+
# step Policy::Pundit( Auth, :user_and_model? ), before: "operation.new"
|
26
|
+
# require "trailblazer/operation/resolver"
|
27
|
+
# step Resolver(), before: "operation.new"
|
28
|
+
|
29
|
+
# step :process
|
30
|
+
|
31
|
+
# class P < self; end
|
32
|
+
# class B < self; end
|
33
|
+
# class M < self; end
|
34
|
+
|
35
|
+
# def process(*); self["x"] = self.class end
|
36
|
+
# end
|
37
|
+
|
38
|
+
# it { A["pipetree"].inspect.must_equal %{[&model.build,&policy.default.eval,>>builder.call,>>operation.new,&process]} }
|
39
|
+
|
40
|
+
# it { r=A.({ some: "params", id: 1 }, { "current_user" => Module })
|
41
|
+
# puts r.inspect
|
42
|
+
|
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
|
data/trailblazer.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_dependency "trailblazer-operation", ">= 0.0.
|
20
|
+
spec.add_dependency "trailblazer-operation", ">= 0.0.10", "< 0.1.0"
|
21
21
|
spec.add_dependency "uber", ">= 0.1.0", "< 0.2.0"
|
22
22
|
spec.add_dependency "reform", ">= 2.2.0", "< 3.0.0"
|
23
23
|
spec.add_dependency "declarative"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trailblazer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: trailblazer-operation
|
@@ -16,14 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.0.
|
19
|
+
version: 0.0.10
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.1.0
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.0.
|
29
|
+
version: 0.0.10
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.1.0
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: uber
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -180,11 +186,11 @@ files:
|
|
180
186
|
- Rakefile
|
181
187
|
- THOUGHTS
|
182
188
|
- doc/Trb-The-Stack.png
|
189
|
+
- doc/operation-2017.png
|
183
190
|
- doc/trb.jpg
|
184
191
|
- lib/trailblazer.rb
|
185
192
|
- lib/trailblazer/dsl.rb
|
186
193
|
- lib/trailblazer/operation/auto_inject.rb
|
187
|
-
- lib/trailblazer/operation/builder.rb
|
188
194
|
- lib/trailblazer/operation/callback.rb
|
189
195
|
- lib/trailblazer/operation/contract.rb
|
190
196
|
- lib/trailblazer/operation/guard.rb
|
@@ -198,15 +204,16 @@ files:
|
|
198
204
|
- lib/trailblazer/operation/pundit.rb
|
199
205
|
- lib/trailblazer/operation/representer.rb
|
200
206
|
- lib/trailblazer/operation/rescue.rb
|
201
|
-
- lib/trailblazer/operation/resolver.rb
|
202
207
|
- lib/trailblazer/operation/validate.rb
|
203
208
|
- lib/trailblazer/operation/wrap.rb
|
204
209
|
- lib/trailblazer/version.rb
|
205
|
-
- test/controller_test.rb
|
206
210
|
- test/docs/auto_inject_test.rb
|
207
211
|
- test/docs/contract_test.rb
|
208
212
|
- test/docs/dry_test.rb
|
213
|
+
- test/docs/fast_test.rb
|
209
214
|
- test/docs/guard_test.rb
|
215
|
+
- test/docs/macro_test.rb
|
216
|
+
- test/docs/model_test.rb
|
210
217
|
- test/docs/nested_test.rb
|
211
218
|
- test/docs/operation_test.rb
|
212
219
|
- test/docs/policy_test.rb
|
@@ -218,7 +225,6 @@ files:
|
|
218
225
|
- test/gemfiles/Gemfile.ruby-2.0
|
219
226
|
- test/gemfiles/Gemfile.ruby-2.3
|
220
227
|
- test/module_test.rb
|
221
|
-
- test/operation/builder_test.rb
|
222
228
|
- test/operation/callback_test.rb
|
223
229
|
- test/operation/contract_test.rb
|
224
230
|
- test/operation/dsl/callback_test.rb
|
@@ -257,16 +263,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
257
263
|
version: '0'
|
258
264
|
requirements: []
|
259
265
|
rubyforge_project:
|
260
|
-
rubygems_version: 2.
|
266
|
+
rubygems_version: 2.6.3
|
261
267
|
signing_key:
|
262
268
|
specification_version: 4
|
263
269
|
summary: A high-level architecture for Ruby and Rails.
|
264
270
|
test_files:
|
265
|
-
- test/controller_test.rb
|
266
271
|
- test/docs/auto_inject_test.rb
|
267
272
|
- test/docs/contract_test.rb
|
268
273
|
- test/docs/dry_test.rb
|
274
|
+
- test/docs/fast_test.rb
|
269
275
|
- test/docs/guard_test.rb
|
276
|
+
- test/docs/macro_test.rb
|
277
|
+
- test/docs/model_test.rb
|
270
278
|
- test/docs/nested_test.rb
|
271
279
|
- test/docs/operation_test.rb
|
272
280
|
- test/docs/policy_test.rb
|
@@ -278,7 +286,6 @@ test_files:
|
|
278
286
|
- test/gemfiles/Gemfile.ruby-2.0
|
279
287
|
- test/gemfiles/Gemfile.ruby-2.3
|
280
288
|
- test/module_test.rb
|
281
|
-
- test/operation/builder_test.rb
|
282
289
|
- test/operation/callback_test.rb
|
283
290
|
- test/operation/contract_test.rb
|
284
291
|
- test/operation/dsl/callback_test.rb
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require "uber/builder"
|
2
|
-
|
3
|
-
# http://trailblazer.to/gems/operation/2.0/builder.html
|
4
|
-
class Trailblazer::Operation
|
5
|
-
module Builder
|
6
|
-
def self.import!(operation, import, user_builder)
|
7
|
-
import.(:>>, user_builder,
|
8
|
-
name: "builder.call",
|
9
|
-
before: "operation.new")
|
10
|
-
|
11
|
-
false # suppress inheritance. dislike. FIXME at some point.
|
12
|
-
end
|
13
|
-
|
14
|
-
# Include this when you want the ::builds DSL.
|
15
|
-
def self.included(includer)
|
16
|
-
includer.extend DSL # ::builds, ::builders
|
17
|
-
includer.| includer.Builder( includer.builders ) # pass class Builders object to our ::import!.
|
18
|
-
end
|
19
|
-
|
20
|
-
DSL = Uber::Builder::DSL
|
21
|
-
end
|
22
|
-
|
23
|
-
DSL.macro!(:Builder, Builder) # Operation::Builder()
|
24
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
class Trailblazer::Operation
|
2
|
-
module Resolver
|
3
|
-
def self.import!(operation, import)
|
4
|
-
operation.extend Model::BuildMethods
|
5
|
-
operation.| operation.Builder(operation.builders)
|
6
|
-
end
|
7
|
-
|
8
|
-
# def self.included(includer)
|
9
|
-
# includer.class_eval do
|
10
|
-
# extend Model::DSL # ::model
|
11
|
-
# extend Model::BuildMethods # ::model!
|
12
|
-
# extend Policy::DSL # ::policy
|
13
|
-
# extend Policy::BuildPermission
|
14
|
-
# end
|
15
|
-
|
16
|
-
# includer.> Model::Build, prepend: true
|
17
|
-
# includer.& Policy::Evaluate, after: Model::Build
|
18
|
-
# end
|
19
|
-
end
|
20
|
-
|
21
|
-
DSL.macro!(:Resolver, Resolver)
|
22
|
-
end
|
data/test/controller_test.rb
DELETED
@@ -1,115 +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
|
-
include Contract
|
32
|
-
include Present
|
33
|
-
|
34
|
-
def model!(params)
|
35
|
-
Comment.new(params[:body])
|
36
|
-
end
|
37
|
-
|
38
|
-
def inspect
|
39
|
-
"<Update: #{@params.inspect} #{self["model"].inspect}>"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
describe "#present with options" do
|
45
|
-
controller! do
|
46
|
-
def show
|
47
|
-
present Comment::Update, params: { current_user: User.new(:admin) }
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
it do
|
52
|
-
controller.show.inspect.must_equal "<Update: {:current_user=>#<struct ControllerTest::User role=:admin>} #<struct ControllerTest::Comment body=nil>>"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
describe "#params!" do
|
57
|
-
controller! do
|
58
|
-
def show
|
59
|
-
present Comment::Update, params: "Cool!"
|
60
|
-
end
|
61
|
-
|
62
|
-
def params!(params)
|
63
|
-
{ body: params }
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
it { controller.show.inspect.must_equal "<Update: {:body=>\"Cool!\"} #<struct ControllerTest::Comment body=\"Cool!\">>" }
|
68
|
-
end
|
69
|
-
|
70
|
-
describe "#form" do
|
71
|
-
class Comment::Create < Trailblazer::Operation
|
72
|
-
def model!(params)
|
73
|
-
Comment.new
|
74
|
-
end
|
75
|
-
|
76
|
-
include Contract
|
77
|
-
contract do
|
78
|
-
def prepopulate!(options)
|
79
|
-
@options = options
|
80
|
-
end
|
81
|
-
attr_reader :options
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
describe "#prepopulate! options" do
|
86
|
-
controller! do
|
87
|
-
def show
|
88
|
-
form Comment::Create
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
it { controller(__body: "Great!").show.options.inspect.must_equal "{:params=>{:__body=>\"Great!\"}}" }
|
93
|
-
end
|
94
|
-
|
95
|
-
describe "with additional options" do
|
96
|
-
controller! do
|
97
|
-
def show
|
98
|
-
form Comment::Create, admin: true
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
it { controller(__body: "Great!").show.options.inspect.must_equal "{:admin=>true, :params=>{:__body=>\"Great!\"}}" }
|
103
|
-
end
|
104
|
-
|
105
|
-
describe "with options and :params" do
|
106
|
-
controller! do
|
107
|
-
def show
|
108
|
-
form Comment::Create, admin: true, params: params.merge(user: User.new)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
it { controller(__body: "Great!").show.options.inspect.must_equal "{:admin=>true, :params=>{:__body=>\"Great!\", :user=>#<struct ControllerTest::User role=nil>}}" }
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
require "trailblazer/operation/builder"
|
3
|
-
|
4
|
-
class BuilderTest < MiniTest::Spec
|
5
|
-
#---
|
6
|
-
# pass proc to Builder[]
|
7
|
-
# this is the puristic way.
|
8
|
-
class A < Trailblazer::Operation
|
9
|
-
builds = ->(klass, options) do
|
10
|
-
return B if options["params"][:sub]
|
11
|
-
klass
|
12
|
-
end
|
13
|
-
|
14
|
-
self.| Builder( builds )
|
15
|
-
self.| :process
|
16
|
-
|
17
|
-
class B < A
|
18
|
-
end
|
19
|
-
|
20
|
-
def process(*); self["x"] = self.class end
|
21
|
-
end
|
22
|
-
|
23
|
-
it { A.()["x"].must_equal A }
|
24
|
-
it { A.({ sub: true })["x"].must_equal A::B }
|
25
|
-
it { A::B["builder"].must_equal nil }
|
26
|
-
|
27
|
-
#---
|
28
|
-
# use manual Builders object
|
29
|
-
MyBuilders = Uber::Builder::Builders.new
|
30
|
-
MyBuilders << ->(options) { return self::B if options["params"][:sub] }
|
31
|
-
|
32
|
-
class Create < Trailblazer::Operation
|
33
|
-
self.| Builder( MyBuilders )
|
34
|
-
self["pipetree"].> ->(input, options) { options["x"] = input.class }
|
35
|
-
end
|
36
|
-
|
37
|
-
it { Create.()["x"].must_equal Create }
|
38
|
-
|
39
|
-
#---
|
40
|
-
#- Builder inheritance
|
41
|
-
class B < A
|
42
|
-
end
|
43
|
-
|
44
|
-
it { B["pipetree"].inspect.must_equal %{[>>operation.new,&process]} }
|
45
|
-
|
46
|
-
#---
|
47
|
-
# use Builder DSL
|
48
|
-
# you don't need to include Builder in the pipetree
|
49
|
-
class ParentOperation < Trailblazer::Operation
|
50
|
-
class Sub < self
|
51
|
-
end
|
52
|
-
|
53
|
-
include Builder
|
54
|
-
builds -> (options) do
|
55
|
-
return Sub if options["params"][:sub]
|
56
|
-
end
|
57
|
-
|
58
|
-
def process(*); self["x"] = self.class end
|
59
|
-
self.| :process
|
60
|
-
end
|
61
|
-
|
62
|
-
it { ParentOperation.({})["x"].must_equal ParentOperation }
|
63
|
-
it { ParentOperation.({ sub: true })["x"].must_equal ParentOperation::Sub }
|
64
|
-
end
|
65
|
-
|
66
|
-
#---
|
67
|
-
# copying via Operation.builders
|
68
|
-
class OperationBuilderClassTest < MiniTest::Spec
|
69
|
-
class SuperOperation < Trailblazer::Operation
|
70
|
-
include Builder
|
71
|
-
|
72
|
-
builds do |options|
|
73
|
-
self::Sub if options["params"][:sub] # Sub is defined in ParentOperation.
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
class ParentOperation < Trailblazer::Operation
|
78
|
-
class Sub < self
|
79
|
-
end
|
80
|
-
|
81
|
-
self.| Builder( SuperOperation.builders )
|
82
|
-
|
83
|
-
def process(*); self["x"] = self.class end
|
84
|
-
self.| :process
|
85
|
-
end
|
86
|
-
|
87
|
-
it { ParentOperation.({})["x"].must_equal ParentOperation }
|
88
|
-
it { ParentOperation.({ sub: true })["x"].must_equal ParentOperation::Sub }
|
89
|
-
end
|