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.
Files changed (72) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.rubocop-https---raw-githubusercontent-com-trailblazer-meta-master-rubocop-yml +101 -0
  4. data/.rubocop.yml +20 -0
  5. data/.rubocop_todo.yml +556 -0
  6. data/.travis.yml +6 -10
  7. data/CHANGES.md +83 -1
  8. data/COMM-LICENSE +46 -75
  9. data/CONTRIBUTING.md +179 -0
  10. data/Gemfile +0 -27
  11. data/{LICENSE.txt → LICENSE} +4 -4
  12. data/README.md +39 -138
  13. data/Rakefile +2 -19
  14. data/lib/trailblazer.rb +3 -17
  15. data/lib/trailblazer/version.rb +3 -1
  16. data/test/test_helper.rb +12 -3
  17. data/trailblazer.gemspec +10 -14
  18. metadata +22 -147
  19. data/doc/Trb-The-Stack.png +0 -0
  20. data/doc/operation-2017.png +0 -0
  21. data/doc/trb.jpg +0 -0
  22. data/lib/trailblazer/dsl.rb +0 -47
  23. data/lib/trailblazer/operation/auto_inject.rb +0 -47
  24. data/lib/trailblazer/operation/callback.rb +0 -35
  25. data/lib/trailblazer/operation/contract.rb +0 -46
  26. data/lib/trailblazer/operation/guard.rb +0 -18
  27. data/lib/trailblazer/operation/model.rb +0 -60
  28. data/lib/trailblazer/operation/module.rb +0 -29
  29. data/lib/trailblazer/operation/nested.rb +0 -113
  30. data/lib/trailblazer/operation/persist.rb +0 -10
  31. data/lib/trailblazer/operation/policy.rb +0 -35
  32. data/lib/trailblazer/operation/procedural/contract.rb +0 -15
  33. data/lib/trailblazer/operation/procedural/validate.rb +0 -22
  34. data/lib/trailblazer/operation/pundit.rb +0 -38
  35. data/lib/trailblazer/operation/representer.rb +0 -31
  36. data/lib/trailblazer/operation/rescue.rb +0 -21
  37. data/lib/trailblazer/operation/test.rb +0 -17
  38. data/lib/trailblazer/operation/validate.rb +0 -68
  39. data/lib/trailblazer/operation/wrap.rb +0 -25
  40. data/test/docs/auto_inject_test.rb +0 -30
  41. data/test/docs/contract_test.rb +0 -525
  42. data/test/docs/dry_test.rb +0 -31
  43. data/test/docs/fast_test.rb +0 -164
  44. data/test/docs/guard_test.rb +0 -169
  45. data/test/docs/macro_test.rb +0 -36
  46. data/test/docs/model_test.rb +0 -75
  47. data/test/docs/nested_test.rb +0 -334
  48. data/test/docs/operation_test.rb +0 -408
  49. data/test/docs/policy_test.rb +0 -2
  50. data/test/docs/pundit_test.rb +0 -133
  51. data/test/docs/representer_test.rb +0 -268
  52. data/test/docs/rescue_test.rb +0 -154
  53. data/test/docs/wrap_test.rb +0 -183
  54. data/test/gemfiles/Gemfile.ruby-1.9 +0 -3
  55. data/test/gemfiles/Gemfile.ruby-2.0 +0 -12
  56. data/test/gemfiles/Gemfile.ruby-2.3 +0 -12
  57. data/test/module_test.rb +0 -100
  58. data/test/operation/callback_test.rb +0 -70
  59. data/test/operation/contract_test.rb +0 -420
  60. data/test/operation/dsl/callback_test.rb +0 -106
  61. data/test/operation/dsl/contract_test.rb +0 -294
  62. data/test/operation/dsl/representer_test.rb +0 -169
  63. data/test/operation/model_test.rb +0 -60
  64. data/test/operation/params_test.rb +0 -36
  65. data/test/operation/persist_test.rb +0 -44
  66. data/test/operation/pipedream_test.rb +0 -59
  67. data/test/operation/pipetree_test.rb +0 -104
  68. data/test/operation/present_test.rb +0 -24
  69. data/test/operation/pundit_test.rb +0 -104
  70. data/test/operation/representer_test.rb +0 -254
  71. data/test/operation/resolver_test.rb +0 -47
  72. data/test/operation_test.rb +0 -143
@@ -1,31 +0,0 @@
1
- require "test_helper"
2
- require "dry/container"
3
-
4
- class DryContainerTest < Minitest::Spec
5
- Song = Struct.new(:id, :title)
6
-
7
- class MyContract < Reform::Form
8
- property :title
9
- validates :title, length: 2..33
10
- end
11
-
12
- my_container = Dry::Container.new
13
- my_container.register("contract.default.class", MyContract)
14
- # my_container.namespace("contract") do
15
- # register("create") { Array }
16
- # end
17
-
18
- #---
19
- #- dependency injection
20
- #- with Dry-container
21
- class Create < Trailblazer::Operation
22
- step Model( Song, :new )
23
- step Contract::Build()
24
- step Contract::Validate()
25
- step Contract::Persist( method: :sync )
26
- end
27
- #:key end
28
-
29
- it { Create.({ title: "A" }, {}, my_container).inspect("model").must_equal %{<Result:false [#<struct DryContainerTest::Song id=nil, title=nil>] >} }
30
- it { Create.({ title: "Anthony's Song" }, {}, my_container).inspect("model").must_equal %{<Result:true [#<struct DryContainerTest::Song id=nil, title="Anthony's Song">] >} }
31
- end
@@ -1,164 +0,0 @@
1
- require "test_helper"
2
-
3
- class DocsFailFastOptionTest < Minitest::Spec
4
- Song = Struct.new(:id, :title) do
5
- def self.find_by(id); nil end
6
- end
7
-
8
- class MyContract < Reform::Form
9
- end
10
-
11
-
12
- #:ffopt
13
- class Update < Trailblazer::Operation
14
- step Model( Song, :find_by )
15
- failure :abort!, fail_fast: true
16
- step Contract::Build( constant: MyContract )
17
- step Contract::Validate( )
18
- failure :handle_invalid_contract! # won't be executed if #abort! is executed.
19
-
20
- def abort!(options, params:, **)
21
- options["result.model.song"] = "Something went wrong with ID #{params[:id]}!"
22
- end
23
- # ..
24
- end
25
- #:ffopt end
26
-
27
- it { Update.(id: 1).inspect("result.model.song", "contract.default").must_equal %{<Result:false [\"Something went wrong with ID 1!\", nil] >} }
28
- it do
29
- #:ffopt-res
30
- result = Update.(id: 1)
31
- result["result.model.song"] #=> "Something went wrong with ID 1!"
32
- #:ffopt-res end
33
- end
34
- end
35
-
36
- class DocsFailFastOptionWithStepTest < Minitest::Spec
37
- Song = Class.new do
38
- def self.find_by(*); Object end
39
- end
40
-
41
- #:ffopt-step
42
- class Update < Trailblazer::Operation
43
- step :empty_id?, fail_fast: true
44
- step Model( Song, :find_by )
45
- failure :handle_empty_db! # won't be executed if #empty_id? returns falsey.
46
-
47
- def empty_id?(options, params:, **)
48
- params[:id] # returns false if :id missing.
49
- end
50
- end
51
- #:ffopt-step end
52
-
53
- it { Update.({ id: nil }).inspect("model").must_equal %{<Result:false [nil] >} }
54
- it { Update.({ id: 1 }).inspect("model").must_equal %{<Result:true [Object] >} }
55
- it do
56
- #:ffopt-step-res
57
- result = Update.({ id: nil })
58
-
59
- result.failure? #=> true
60
- result["model"] #=> nil
61
- #:ffopt-step-res end
62
- end
63
- end
64
-
65
- class DocsPassFastWithStepOptionTest < Minitest::Spec
66
- Song = Struct.new(:id, :title) do
67
- def self.find_by(id); nil end
68
- end
69
-
70
- class MyContract < Reform::Form
71
- end
72
-
73
- #:pfopt-step
74
- class Update < Trailblazer::Operation
75
- step Model( Song, :find_by )
76
- failure :abort!, fail_fast: true
77
- step Contract::Build( constant: MyContract )
78
- step Contract::Validate( )
79
- failure :handle_invalid_contract! # won't be executed if #abort! is executed.
80
-
81
- def abort!(options, params:, **)
82
- options["result.model.song"] = "Something went wrong with ID #{params[:id]}!"
83
- end
84
- # ..
85
- end
86
- #:pfopt-step end
87
-
88
- it { Update.(id: 1).inspect("result.model.song", "contract.default").must_equal %{<Result:false [\"Something went wrong with ID 1!\", nil] >} }
89
- it do
90
- #:pfopt-step-res
91
- result = Update.(id: 1)
92
- result["result.model.song"] #=> "Something went wrong with ID 1!"
93
- #:pfopt-step-res end
94
- end
95
- end
96
-
97
- class DocsFailFastMethodTest < Minitest::Spec
98
- Song = Struct.new(:id, :title) do
99
- def self.find_by(id); nil end
100
- end
101
-
102
- #:ffmeth
103
- class Update < Trailblazer::Operation
104
- step :filter_params! # emits fail_fast!
105
- step Model( Song, :find_by )
106
- failure :handle_fail!
107
-
108
- def filter_params!(options, params:, **)
109
- unless params[:id]
110
- options["result.params"] = "No ID in params!"
111
- return Railway.fail_fast!
112
- end
113
- end
114
-
115
- def handle_fail!(options, **)
116
- options["my.status"] = "Broken!"
117
- end
118
- end
119
- #:ffmeth end
120
-
121
- it { Update.({}).inspect("result.params", "my.status").must_equal %{<Result:false [\"No ID in params!\", nil] >} }
122
- it do
123
- #:ffmeth-res
124
- result = Update.(id: 1)
125
- result["result.params"] #=> "No ID in params!"
126
- result["my.status"] #=> nil
127
- #:ffmeth-res end
128
- end
129
- end
130
-
131
- class DocsPassFastMethodTest < Minitest::Spec
132
- Song = Struct.new(:id, :title) do
133
- def save; end
134
- end
135
-
136
- class MyContract < Reform::Form
137
- end
138
-
139
- #:pfmeth
140
- class Create < Trailblazer::Operation
141
- step Model( Song, :new )
142
- step :empty_model! # emits pass_fast!
143
- step Contract::Build( constant: MyContract )
144
- # ..
145
-
146
- def empty_model!(options, is_empty:, model:, **)
147
- return unless is_empty
148
- model.save
149
- Railway.pass_fast!
150
- end
151
- end
152
- #:pfmeth end
153
-
154
- it { Create.({ title: "Tyrant"}, "is_empty" => true).inspect("model").must_equal %{<Result:true [#<struct DocsPassFastMethodTest::Song id=nil, title=nil>] >} }
155
- it do
156
- #:pfmeth-res
157
- result = Create.({}, "is_empty" => true)
158
- result["model"] #=> #<Song id=nil, title=nil>
159
- #:pfmeth-res end
160
- end
161
- end
162
-
163
- # fail!
164
- # pass!
@@ -1,169 +0,0 @@
1
- require "test_helper"
2
-
3
- #--
4
- # with proc
5
- class DocsGuardProcTest < Minitest::Spec
6
- # test without KWs, only options.
7
- class Update < Trailblazer::Operation
8
- step Policy::Guard( ->(options) { options["params"][:pass] } )
9
- step ->(options, *) { options["x"] = true }
10
- end
11
-
12
- it { Update.(pass: false)["x"].must_equal nil }
13
- it { Update.(pass: true)["x"].must_equal true }
14
- # TODO: test excp when current_user not available
15
-
16
- #:proc
17
- class Create < Trailblazer::Operation
18
- step Policy::Guard( ->(options, params:, **) { params[:pass] } )
19
- #~pipeonly
20
- step :process
21
-
22
- def process(*)
23
- self["x"] = true
24
- end
25
- #~pipeonly end
26
- end
27
- #:proc end
28
-
29
- it { Create.(pass: false)["x"].must_equal nil }
30
- it { Create.(pass: true)["x"].must_equal true }
31
-
32
- #- result object, guard
33
- it { Create.(pass: true)["result.policy.default"].success?.must_equal true }
34
- it { Create.(pass: false)["result.policy.default"].success?.must_equal false }
35
-
36
-
37
-
38
-
39
- #---
40
- #- Guard inheritance
41
- class New < Create
42
- step Policy::Guard( ->(options, current_user:, **) { current_user } ), override: true
43
- end
44
-
45
- it { New["pipetree"].inspect.must_equal %{[>operation.new,>policy.default.eval,>process]} }
46
- end
47
-
48
- #---
49
- # with Callable
50
- class DocsGuardTest < Minitest::Spec
51
- #:callable
52
- class MyGuard
53
- include Uber::Callable
54
-
55
- def call(options, params:, **)
56
- params[:pass]
57
- end
58
- end
59
- #:callable end
60
-
61
- #:callable-op
62
- class Create < Trailblazer::Operation
63
- step Policy::Guard( MyGuard.new )
64
- #~pipe-only
65
- step :process
66
- def process(*); self[:x] = true; end
67
- #~pipe-only end
68
- end
69
- #:callable-op end
70
-
71
- it { Create.(pass: false)[:x].must_equal nil }
72
- it { Create.(pass: true)[:x].must_equal true }
73
- end
74
-
75
- #---
76
- # with method
77
- class DocsGuardMethodTest < Minitest::Spec
78
- #:method
79
- class Create < Trailblazer::Operation
80
- step Policy::Guard( :pass? )
81
-
82
- def pass?(options, params:, **)
83
- params[:pass]
84
- end
85
- #~pipe-onlyy
86
- step :process
87
- def process(*); self["x"] = true; end
88
- #~pipe-onlyy end
89
- end
90
- #:method end
91
-
92
- it { Create.(pass: false).inspect("x").must_equal %{<Result:false [nil] >} }
93
- it { Create.(pass: true).inspect("x").must_equal %{<Result:true [true] >} }
94
- end
95
-
96
- #---
97
- # with name:
98
- class DocsGuardNamedTest < Minitest::Spec
99
- #:name
100
- class Create < Trailblazer::Operation
101
- step Policy::Guard( ->(options, current_user:, **) { current_user }, name: :user )
102
- # ...
103
- end
104
- #:name end
105
-
106
- it { Create.({}, "current_user" => nil )["result.policy.user"].success?.must_equal false }
107
- it { Create.({}, "current_user" => Module)["result.policy.user"].success?.must_equal true }
108
-
109
- it {
110
- #:name-result
111
- result = Create.({}, "current_user" => true)
112
- result["result.policy.user"].success? #=> true
113
- #:name-result end
114
- }
115
- end
116
-
117
- #---
118
- # dependency injection
119
- class DocsGuardInjectionTest < Minitest::Spec
120
- #:di-op
121
- class Create < Trailblazer::Operation
122
- step Policy::Guard( ->(options, current_user:, **) { current_user == Module } )
123
- end
124
- #:di-op end
125
-
126
- it { Create.({}, "current_user" => Module).inspect("").must_equal %{<Result:true [nil] >} }
127
- it {
128
- result =
129
- #:di-call
130
- Create.({},
131
- "current_user" => Module,
132
- "policy.default.eval" => Trailblazer::Operation::Policy::Guard.build(->(options) { false })
133
- )
134
- #:di-call end
135
- result.inspect("").must_equal %{<Result:false [nil] >} }
136
- end
137
-
138
- #---
139
- # missing current_user throws exception
140
- class DocsGuardMissingKeywordTest < Minitest::Spec
141
- class Create < Trailblazer::Operation
142
- step Policy::Guard( ->(options, current_user:, **) { current_user == Module } )
143
- end
144
-
145
- it { assert_raises(ArgumentError) { Create.() } }
146
- it { Create.({}, "current_user" => Module).success?.must_equal true }
147
- end
148
-
149
- #---
150
- # before:
151
- class DocsGuardPositionTest < Minitest::Spec
152
- #:before
153
- class Create < Trailblazer::Operation
154
- step :model!
155
- step Policy::Guard( :authorize! ),
156
- before: :model!
157
- end
158
- #:before end
159
-
160
- it { Create["pipetree"].inspect.must_equal %{[>operation.new,>policy.default.eval,>model!]} }
161
- it do
162
- #:before-pipe
163
- puts Create["pipetree"].inspect(style: :rows) #=>
164
- # 0 ========================>operation.new
165
- # 1 ==================>policy.default.eval
166
- # 2 ===============================>model!
167
- #:before-pipe end
168
- end
169
- end
@@ -1,36 +0,0 @@
1
- require "test_helper"
2
-
3
- class DocsMacroTest < Minitest::Spec
4
- #:simple
5
- module Macro
6
- def self.MyPolicy(allowed_role: "admin")
7
- step = ->(input, options) { options["current_user"].type == allowed_role }
8
-
9
- [ step, name: "my_policy.#{allowed_role}" ] # :before, :replace, etc. work, too.
10
- end
11
- end
12
- #:simple end
13
-
14
- #:simple-op
15
- class Create < Trailblazer::Operation
16
- step Macro::MyPolicy( allowed_role: "manager" )
17
- # ..
18
- end
19
- #:simple-op end
20
-
21
- =begin
22
- it do
23
- #:simple-pipe
24
- puts Create["pipetree"].inspect(style: :rows) #=>
25
- 0 ========================>operation.new
26
- 1 ====================>my_policy.manager
27
- #:simple-pipe end
28
- end
29
- =end
30
-
31
- it { Create["pipetree"].inspect.must_equal %{[>operation.new,>my_policy.manager]} }
32
- end
33
-
34
- # injectable option
35
- # nested pipe
36
- # using macros in macros
@@ -1,75 +0,0 @@
1
- require "test_helper"
2
-
3
- class DocsModelTest < Minitest::Spec
4
- Song = Struct.new(:id, :title) do
5
- def self.find_by(id:nil)
6
- id.nil? ? nil : new(id)
7
- end
8
-
9
- def self.[](id)
10
- id.nil? ? nil : new(id+99)
11
- end
12
- end
13
-
14
- #:op
15
- class Create < Trailblazer::Operation
16
- step Model( Song, :new )
17
- # ..
18
- end
19
- #:op end
20
-
21
- it do
22
- #:create
23
- result = Create.({})
24
- result["model"] #=> #<struct Song id=nil, title=nil>
25
- #:create end
26
-
27
- result["model"].inspect.must_equal %{#<struct DocsModelTest::Song id=nil, title=nil>}
28
- end
29
-
30
- #:update
31
- class Update < Trailblazer::Operation
32
- step Model( Song, :find_by )
33
- # ..
34
- end
35
- #:update end
36
-
37
- it do
38
- #:update-ok
39
- result = Update.({ id: 1 })
40
- result["model"] #=> #<struct Song id=1, title="Roxanne">
41
- #:update-ok end
42
-
43
- result["model"].inspect.must_equal %{#<struct DocsModelTest::Song id=1, title=nil>}
44
- end
45
-
46
- it do
47
- #:update-fail
48
- result = Update.({})
49
- result["model"] #=> nil
50
- result.success? #=> false
51
- #:update-fail end
52
-
53
- result["model"].must_be_nil
54
- result.success?.must_equal false
55
- end
56
-
57
- #:show
58
- class Show < Trailblazer::Operation
59
- step Model( Song, :[] )
60
- # ..
61
- end
62
- #:show end
63
-
64
- it do
65
- result = Show.({ id: 1 })
66
-
67
- #:show-ok
68
- result = Show.({ id: 1 })
69
- result["model"] #=> #<struct Song id=1, title="Roxanne">
70
- #:show-ok end
71
-
72
- result.success?.must_equal true
73
- result["model"].inspect.must_equal %{#<struct DocsModelTest::Song id=100, title=nil>}
74
- end
75
- end