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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +13 -0
  3. data/COMM-LICENSE +21 -21
  4. data/Gemfile +3 -0
  5. data/README.md +15 -77
  6. data/Rakefile +1 -2
  7. data/doc/operation-2017.png +0 -0
  8. data/lib/trailblazer.rb +0 -1
  9. data/lib/trailblazer/operation/callback.rb +10 -19
  10. data/lib/trailblazer/operation/contract.rb +7 -8
  11. data/lib/trailblazer/operation/guard.rb +4 -13
  12. data/lib/trailblazer/operation/model.rb +30 -32
  13. data/lib/trailblazer/operation/nested.rb +21 -32
  14. data/lib/trailblazer/operation/persist.rb +4 -8
  15. data/lib/trailblazer/operation/policy.rb +5 -15
  16. data/lib/trailblazer/operation/pundit.rb +8 -17
  17. data/lib/trailblazer/operation/rescue.rb +17 -17
  18. data/lib/trailblazer/operation/validate.rb +34 -21
  19. data/lib/trailblazer/operation/wrap.rb +12 -25
  20. data/lib/trailblazer/version.rb +1 -1
  21. data/test/docs/dry_test.rb +4 -4
  22. data/test/docs/fast_test.rb +164 -0
  23. data/test/docs/guard_test.rb +2 -2
  24. data/test/docs/macro_test.rb +36 -0
  25. data/test/docs/model_test.rb +52 -0
  26. data/test/docs/nested_test.rb +101 -4
  27. data/test/docs/operation_test.rb +225 -1
  28. data/test/docs/pundit_test.rb +18 -17
  29. data/test/docs/rescue_test.rb +3 -3
  30. data/test/docs/wrap_test.rb +1 -0
  31. data/test/operation/callback_test.rb +5 -5
  32. data/test/operation/contract_test.rb +30 -19
  33. data/test/operation/dsl/callback_test.rb +2 -2
  34. data/test/operation/dsl/contract_test.rb +4 -4
  35. data/test/operation/model_test.rb +12 -57
  36. data/test/operation/persist_test.rb +7 -7
  37. data/test/operation/pipedream_test.rb +9 -9
  38. data/test/operation/pipetree_test.rb +5 -5
  39. data/test/operation/pundit_test.rb +7 -7
  40. data/test/operation/resolver_test.rb +47 -47
  41. data/trailblazer.gemspec +1 -1
  42. metadata +18 -11
  43. data/lib/trailblazer/operation/builder.rb +0 -24
  44. data/lib/trailblazer/operation/resolver.rb +0 -22
  45. data/test/controller_test.rb +0 -115
  46. 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
- self.| Policy::Pundit( Auth, :only_user? )
21
- self.| :process
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
- self.| Model( Song, :new ), before: "policy.default.eval"
53
+ step Model( Song, :new ), before: "policy.default.eval"
54
54
  end
55
55
 
56
- it { Show["pipetree"].inspect.must_equal %{[>>operation.new,&model.build,&policy.default.eval,&process]} }
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
- self.| Model Song, :update
79
- self.| Policy::Pundit( Auth, :user_and_model? )
80
- self.| :process
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
- 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
- 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"
28
-
29
- self.| :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
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
@@ -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.9"
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.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: 2016-12-15 00:00:00.000000000 Z
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.9
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.9
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.4.8
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
@@ -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