trailblazer 1.1.2 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +10 -7
  3. data/CHANGES.md +108 -0
  4. data/COMM-LICENSE +91 -0
  5. data/Gemfile +18 -4
  6. data/LICENSE.txt +7 -20
  7. data/README.md +55 -15
  8. data/Rakefile +21 -2
  9. data/draft-1.2.rb +7 -0
  10. data/lib/trailblazer.rb +17 -4
  11. data/lib/trailblazer/dsl.rb +47 -0
  12. data/lib/trailblazer/operation/auto_inject.rb +47 -0
  13. data/lib/trailblazer/operation/builder.rb +18 -18
  14. data/lib/trailblazer/operation/callback.rb +31 -38
  15. data/lib/trailblazer/operation/contract.rb +46 -0
  16. data/lib/trailblazer/operation/controller.rb +45 -27
  17. data/lib/trailblazer/operation/guard.rb +24 -0
  18. data/lib/trailblazer/operation/model.rb +41 -33
  19. data/lib/trailblazer/operation/nested.rb +43 -0
  20. data/lib/trailblazer/operation/params.rb +13 -0
  21. data/lib/trailblazer/operation/persist.rb +13 -0
  22. data/lib/trailblazer/operation/policy.rb +26 -72
  23. data/lib/trailblazer/operation/present.rb +19 -0
  24. data/lib/trailblazer/operation/procedural/contract.rb +15 -0
  25. data/lib/trailblazer/operation/procedural/validate.rb +22 -0
  26. data/lib/trailblazer/operation/pundit.rb +42 -0
  27. data/lib/trailblazer/operation/representer.rb +25 -92
  28. data/lib/trailblazer/operation/rescue.rb +23 -0
  29. data/lib/trailblazer/operation/resolver.rb +18 -24
  30. data/lib/trailblazer/operation/validate.rb +50 -0
  31. data/lib/trailblazer/operation/wrap.rb +37 -0
  32. data/lib/trailblazer/version.rb +1 -1
  33. data/test/{operation/controller_test.rb → controller_test.rb} +8 -4
  34. data/test/docs/auto_inject_test.rb +30 -0
  35. data/test/docs/contract_test.rb +429 -0
  36. data/test/docs/dry_test.rb +31 -0
  37. data/test/docs/guard_test.rb +143 -0
  38. data/test/docs/nested_test.rb +117 -0
  39. data/test/docs/policy_test.rb +2 -0
  40. data/test/docs/pundit_test.rb +109 -0
  41. data/test/docs/representer_test.rb +268 -0
  42. data/test/docs/rescue_test.rb +153 -0
  43. data/test/docs/wrap_test.rb +174 -0
  44. data/test/gemfiles/Gemfile.ruby-1.9 +3 -0
  45. data/test/gemfiles/Gemfile.ruby-2.0 +12 -0
  46. data/test/gemfiles/Gemfile.ruby-2.3 +12 -0
  47. data/test/module_test.rb +22 -15
  48. data/test/operation/builder_test.rb +66 -18
  49. data/test/operation/callback_test.rb +70 -0
  50. data/test/operation/contract_test.rb +385 -15
  51. data/test/operation/dsl/callback_test.rb +18 -30
  52. data/test/operation/dsl/contract_test.rb +209 -19
  53. data/test/operation/dsl/representer_test.rb +42 -15
  54. data/test/operation/guard_test.rb +1 -147
  55. data/test/operation/model_test.rb +105 -0
  56. data/test/operation/params_test.rb +36 -0
  57. data/test/operation/persist_test.rb +44 -0
  58. data/test/operation/pipedream_test.rb +59 -0
  59. data/test/operation/pipetree_test.rb +104 -0
  60. data/test/operation/present_test.rb +24 -0
  61. data/test/operation/pundit_test.rb +104 -0
  62. data/test/{representer_test.rb → operation/representer_test.rb} +58 -42
  63. data/test/operation/resolver_test.rb +34 -70
  64. data/test/operation_test.rb +57 -189
  65. data/test/test_helper.rb +23 -3
  66. data/trailblazer.gemspec +8 -7
  67. metadata +91 -59
  68. data/gemfiles/Gemfile.rails.lock +0 -130
  69. data/gemfiles/Gemfile.reform-2.0 +0 -6
  70. data/gemfiles/Gemfile.reform-2.1 +0 -7
  71. data/lib/trailblazer/autoloading.rb +0 -15
  72. data/lib/trailblazer/endpoint.rb +0 -31
  73. data/lib/trailblazer/operation.rb +0 -175
  74. data/lib/trailblazer/operation/collection.rb +0 -6
  75. data/lib/trailblazer/operation/dispatch.rb +0 -3
  76. data/lib/trailblazer/operation/model/dsl.rb +0 -29
  77. data/lib/trailblazer/operation/model/external.rb +0 -34
  78. data/lib/trailblazer/operation/policy/guard.rb +0 -35
  79. data/lib/trailblazer/operation/uploaded_file.rb +0 -77
  80. data/test/callback_test.rb +0 -104
  81. data/test/collection_test.rb +0 -57
  82. data/test/model_test.rb +0 -148
  83. data/test/operation/external_model_test.rb +0 -71
  84. data/test/operation/policy_test.rb +0 -97
  85. data/test/operation/reject_test.rb +0 -34
  86. data/test/rollback_test.rb +0 -47
@@ -1,130 +0,0 @@
1
- PATH
2
- remote: ../
3
- specs:
4
- trailblazer (0.2.2)
5
- actionpack (>= 3.0.0)
6
- reform (>= 1.2.0)
7
- uber (>= 0.0.10)
8
-
9
- GEM
10
- remote: http://rubygems.org/
11
- specs:
12
- actionmailer (4.1.1)
13
- actionpack (= 4.1.1)
14
- actionview (= 4.1.1)
15
- mail (~> 2.5.4)
16
- actionpack (4.1.1)
17
- actionview (= 4.1.1)
18
- activesupport (= 4.1.1)
19
- rack (~> 1.5.2)
20
- rack-test (~> 0.6.2)
21
- actionview (4.1.1)
22
- activesupport (= 4.1.1)
23
- builder (~> 3.1)
24
- erubis (~> 2.7.0)
25
- activemodel (4.1.1)
26
- activesupport (= 4.1.1)
27
- builder (~> 3.1)
28
- activerecord (4.1.1)
29
- activemodel (= 4.1.1)
30
- activesupport (= 4.1.1)
31
- arel (~> 5.0.0)
32
- activesupport (4.1.1)
33
- i18n (~> 0.6, >= 0.6.9)
34
- json (~> 1.7, >= 1.7.7)
35
- minitest (~> 5.1)
36
- thread_safe (~> 0.1)
37
- tzinfo (~> 1.1)
38
- arel (5.0.1.20140414130214)
39
- builder (3.2.2)
40
- celluloid (0.16.0)
41
- timers (~> 4.0.0)
42
- connection_pool (2.0.0)
43
- disposable (0.0.9)
44
- representable (~> 2.0)
45
- uber
46
- erubis (2.7.0)
47
- hitimes (1.2.2)
48
- i18n (0.6.11)
49
- json (1.8.1)
50
- mail (2.5.4)
51
- mime-types (~> 1.16)
52
- treetop (~> 1.4.8)
53
- mime-types (1.25.1)
54
- mini_portile (0.6.2)
55
- minitest (5.4.2)
56
- multi_json (1.11.0)
57
- nokogiri (1.6.6.2)
58
- mini_portile (~> 0.6.0)
59
- polyglot (0.3.5)
60
- rack (1.5.2)
61
- rack-test (0.6.2)
62
- rack (>= 1.0)
63
- rails (4.1.1)
64
- actionmailer (= 4.1.1)
65
- actionpack (= 4.1.1)
66
- actionview (= 4.1.1)
67
- activemodel (= 4.1.1)
68
- activerecord (= 4.1.1)
69
- activesupport (= 4.1.1)
70
- bundler (>= 1.3.0, < 2.0)
71
- railties (= 4.1.1)
72
- sprockets-rails (~> 2.0)
73
- railties (4.1.1)
74
- actionpack (= 4.1.1)
75
- activesupport (= 4.1.1)
76
- rake (>= 0.8.7)
77
- thor (>= 0.18.1, < 2.0)
78
- rake (10.3.2)
79
- redis (3.1.0)
80
- redis-namespace (1.5.1)
81
- redis (~> 3.0, >= 3.0.4)
82
- reform (1.2.6)
83
- activemodel
84
- disposable (~> 0.0.5)
85
- representable (~> 2.1.0)
86
- uber (~> 0.0.11)
87
- representable (2.1.8)
88
- multi_json
89
- nokogiri
90
- uber (~> 0.0.7)
91
- responders (1.1.2)
92
- railties (>= 3.2, < 4.2)
93
- sidekiq (3.1.4)
94
- celluloid (>= 0.15.2)
95
- connection_pool (>= 2.0.0)
96
- json
97
- redis (>= 3.0.6)
98
- redis-namespace (>= 1.3.1)
99
- sprockets (3.1.0)
100
- rack (~> 1.0)
101
- sprockets-rails (2.3.1)
102
- actionpack (>= 3.0)
103
- activesupport (>= 3.0)
104
- sprockets (>= 2.8, < 4.0)
105
- sqlite3 (1.3.9)
106
- thor (0.19.1)
107
- thread_safe (0.3.4)
108
- timers (4.0.1)
109
- hitimes
110
- treetop (1.4.15)
111
- polyglot
112
- polyglot (>= 0.3.1)
113
- tzinfo (1.2.2)
114
- thread_safe (~> 0.1)
115
- uber (0.0.13)
116
-
117
- PLATFORMS
118
- ruby
119
-
120
- DEPENDENCIES
121
- activerecord
122
- bundler
123
- minitest
124
- rails
125
- railties
126
- rake
127
- responders
128
- sidekiq (~> 3.1.0)
129
- sqlite3
130
- trailblazer!
@@ -1,6 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gemspec path: '../'
4
-
5
- gem "reform", "~> 2.0.5"
6
- gem "multi_json"
@@ -1,7 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gemspec path: '../'
4
-
5
- gem "reform", github: "apotonick/reform" #"~> 2.1.0.rc1"
6
- gem "roar", github: "apotonick/roar" # "1.1.0"
7
- gem "multi_json"
@@ -1,15 +0,0 @@
1
- Trailblazer.class_eval do
2
- autoload :NotAuthorizedError, "trailblazer/operation/policy"
3
- end
4
-
5
- Trailblazer::Operation.class_eval do
6
- autoload :Controller, "trailblazer/operation/controller"
7
- autoload :Model, "trailblazer/operation/model"
8
- autoload :Collection, "trailblazer/operation/collection"
9
- autoload :Dispatch, "trailblazer/operation/dispatch" # TODO: remove in 1.2.
10
- autoload :Callback, "trailblazer/operation/callback"
11
- autoload :Module, "trailblazer/operation/module"
12
- autoload :Representer,"trailblazer/operation/representer"
13
- autoload :Policy, "trailblazer/operation/policy"
14
- autoload :Resolver, "trailblazer/operation/resolver"
15
- end
@@ -1,31 +0,0 @@
1
- module Trailblazer
2
- # Encapsulates HTTP-specific logic needed before running an operation.
3
- # Right now, all this does is #document_body! which figures out whether or not to pass the request body
4
- # into params, so the operation can use a representer to deserialize the original document.
5
- # To be used in Hanami, Roda, Rails, etc.
6
- class Endpoint
7
- def initialize(operation_class, params, request, options)
8
- @operation_class = operation_class
9
- @params = params
10
- @request = request
11
- @is_document = options[:is_document]
12
- end
13
-
14
- def call
15
- document_body! if @is_document
16
- yield @params# Create.run(params)
17
- end
18
-
19
- private
20
- attr_reader :params, :operation_class, :request
21
-
22
- def document_body!
23
- # this is what happens:
24
- # respond_with Comment::Update::JSON.run(params.merge(comment: request.body.string))
25
- concept_name = operation_class.model_class.to_s.underscore # this could be renamed to ::concept_class soon.
26
- request_body = request.body.respond_to?(:string) ? request.body.string : request.body.read
27
-
28
- params.merge!(concept_name => request_body)
29
- end
30
- end
31
- end
@@ -1,175 +0,0 @@
1
- require "reform"
2
-
3
- module Trailblazer
4
- class Operation
5
- require "trailblazer/operation/builder"
6
- extend Builder # imports ::builder_class and ::build_operation.
7
-
8
- extend Uber::InheritableAttr
9
- inheritable_attr :contract_class
10
- self.contract_class = Reform::Form.clone
11
-
12
- class << self
13
- def run(params, &block) # Endpoint behaviour
14
- res, op = build_operation(params).run
15
-
16
- if block_given?
17
- yield op if res
18
- return op
19
- end
20
-
21
- [res, op]
22
- end
23
-
24
- # Like ::run, but yield block when invalid.
25
- def reject(*args)
26
- res, op = run(*args)
27
- yield op if res == false
28
- op
29
- end
30
-
31
- # ::call only returns the Operation instance (or whatever was returned from #validate).
32
- # This is useful in tests or in irb, e.g. when using Op as a factory and you already know it's valid.
33
- def call(params)
34
- build_operation(params, raise_on_invalid: true).run.last
35
- end
36
-
37
- def [](*args) # TODO: remove in 1.2.
38
- warn "[Trailblazer] Operation[] is deprecated. Please use Operation.() and have a nice day."
39
- call(*args)
40
- end
41
-
42
- # Runs #setup! but doesn't process the operation.
43
- def present(params)
44
- build_operation(params)
45
- end
46
-
47
- # This is a DSL method. Use ::contract_class and ::contract_class= for the explicit version.
48
- # Op.contract #=> returns contract class
49
- # Op.contract do .. end # defines contract
50
- # Op.contract CommentForm # copies (and subclasses) external contract.
51
- # Op.contract CommentForm do .. end # copies and extends contract.
52
- def contract(constant=nil, &block)
53
- return contract_class unless constant or block_given?
54
-
55
- self.contract_class= Class.new(constant) if constant
56
- contract_class.class_eval(&block) if block_given?
57
- end
58
- end
59
-
60
-
61
- def initialize(params, options={})
62
- @options = options
63
- @valid = true
64
-
65
- setup!(params) # assign/find the model
66
- end
67
-
68
- # Operation.run(body: "Fabulous!") #=> [true, <Comment body: "Fabulous!">]
69
- def run
70
- process(@params)
71
-
72
- [valid?, self]
73
- end
74
-
75
- attr_reader :model
76
-
77
- def errors
78
- contract.errors
79
- end
80
-
81
- def valid?
82
- @valid
83
- end
84
-
85
- def contract(*args)
86
- contract!(*args)
87
- end
88
-
89
- private
90
- module Setup
91
- attr_writer :model
92
-
93
- def setup!(params)
94
- params = assign_params!(params)
95
- setup_params!(params)
96
- build_model!(params)
97
- params # TODO: test me.
98
- end
99
-
100
- def assign_params!(params)
101
- @params = params!(params)
102
- end
103
-
104
- # Overwrite #params! if you need to change its structure, by returning a new params object
105
- # from this method.
106
- # This is helpful if you don't want to change the original via #setup_params!.
107
- def params!(params)
108
- params
109
- end
110
-
111
- def setup_params!(params)
112
- end
113
-
114
- def build_model!(*args)
115
- assign_model!(*args) # @model = ..
116
- setup_model!(*args)
117
- end
118
-
119
- def assign_model!(*args)
120
- @model = model!(*args)
121
- end
122
-
123
- # Implement #model! to find/create your operation model (if required).
124
- def model!(params)
125
- end
126
-
127
- # Override to add attributes that can be infered from params.
128
- def setup_model!(params)
129
- end
130
- end
131
- include Setup
132
-
133
- def validate(params, model=nil, contract_class=nil)
134
- contract!(model, contract_class)
135
-
136
- if @valid = validate_contract(params)
137
- yield contract if block_given?
138
- else
139
- raise!(contract)
140
- end
141
-
142
- @valid
143
- end
144
-
145
- def validate_contract(params)
146
- contract.validate(params)
147
- end
148
-
149
- def invalid!(result=self)
150
- @valid = false
151
- result
152
- end
153
-
154
- # When using Op.(), an invalid contract will raise an exception.
155
- def raise!(contract)
156
- raise InvalidContract.new(contract.errors.to_s) if @options[:raise_on_invalid]
157
- end
158
-
159
- # Instantiate the contract, either by using the user's contract passed into #validate
160
- # or infer the Operation contract.
161
- def contract_for(model=nil, contract_class=nil)
162
- model ||= self.model
163
- contract_class ||= self.class.contract_class
164
-
165
- contract_class.new(model)
166
- end
167
-
168
- def contract!(*args)
169
- @contract ||= contract_for(*args)
170
- end
171
-
172
- class InvalidContract < RuntimeError
173
- end
174
- end
175
- end
@@ -1,6 +0,0 @@
1
- module Trailblazer::Operation::Collection
2
- # Collection does not produce a contract.
3
- def present
4
- self
5
- end
6
- end
@@ -1,3 +0,0 @@
1
- require "trailblazer/operation/callback"
2
- # TODO: deprecate this module.
3
- Trailblazer::Operation::Dispatch = Trailblazer::Operation::Callback
@@ -1,29 +0,0 @@
1
- class Trailblazer::Operation
2
- module Model
3
- # Imports ::model and ::action into an operation.
4
- module DSL
5
- def self.extended(extender)
6
- extender.extend Uber::InheritableAttr
7
- extender.inheritable_attr :config
8
- extender.config = {}
9
- end
10
-
11
- def model(name, action=nil)
12
- self.config[:model] = name
13
- action(action) if action # coolest line ever.
14
- end
15
-
16
- def action(name)
17
- self.config[:action] = name
18
- end
19
-
20
- def action_name # considered private.
21
- self.config[:action] or :create
22
- end
23
-
24
- def model_class # considered private.
25
- self.config[:model] or raise "[Trailblazer] You didn't call Operation::model."
26
- end
27
- end
28
- end
29
- end
@@ -1,34 +0,0 @@
1
- require "trailblazer/operation/model"
2
-
3
- class Trailblazer::Operation
4
- module Model
5
- # Builds (finds or creates) the model _before_ the operation is instantiated.
6
- # Passes the model instance into the builder with the following signature.
7
- #
8
- # builds ->(model, params)
9
- #
10
- # The initializer will now expect you to pass the model in via options[:model]. This
11
- # happens automatically when coming from a builder.
12
- module External
13
- def self.included(includer)
14
- includer.extend Model::DSL
15
- includer.extend Model::BuildModel
16
- includer.extend ClassMethods
17
- end
18
-
19
- def assign_model!(*) # i don't like to "disable" the `@model =` like this but it's the simplest for now.
20
- @model = @options[:model]
21
- end
22
-
23
-
24
- module ClassMethods
25
- private
26
- def build_operation(params, options={}) # TODO: merge with Resolver::build_operation.
27
- model = model!(params)
28
- build_operation_class(model, params). # calls builds->(model, params).
29
- new(params, options.merge(model: model))
30
- end
31
- end
32
- end
33
- end
34
- end