trailblazer 2.0.7 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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