rest_my_case 1.10.9 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +5 -13
  2. data/README.md +330 -2
  3. data/lib/rest_my_case/base.rb +46 -21
  4. data/lib/rest_my_case/context/base.rb +11 -0
  5. data/lib/rest_my_case/context/schema_validator/base.rb +27 -0
  6. data/lib/rest_my_case/context/schema_validator/compel.rb +36 -0
  7. data/lib/rest_my_case/context/status.rb +2 -0
  8. data/lib/rest_my_case/defense_attorney/base.rb +1 -1
  9. data/lib/rest_my_case/http_status.rb +5 -8
  10. data/lib/rest_my_case/judge/base.rb +19 -14
  11. data/lib/rest_my_case/status.rb +13 -12
  12. data/lib/rest_my_case/trial/case.rb +3 -3
  13. data/lib/rest_my_case/validator.rb +3 -8
  14. data/lib/rest_my_case/version.rb +1 -1
  15. data/lib/rest_my_case.rb +0 -4
  16. data/rest_my_case.gemspec +1 -1
  17. data/spec/rest_my_case/accusation_attorneys/base_spec.rb +1 -1
  18. data/spec/rest_my_case/accusation_attorneys/each_spec.rb +1 -1
  19. data/spec/rest_my_case/accusation_attorneys/format_spec.rb +2 -2
  20. data/spec/rest_my_case/base/context_accessor_spec.rb +29 -0
  21. data/spec/rest_my_case/base/context_reader_spec.rb +21 -0
  22. data/spec/rest_my_case/base/context_writer_spec.rb +23 -0
  23. data/spec/rest_my_case/base/dependencies_spec.rb +14 -0
  24. data/spec/rest_my_case/base/invoke!_spec.rb +140 -0
  25. data/spec/rest_my_case/base/invoke_spec.rb +29 -0
  26. data/spec/rest_my_case/{base_spec.rb → base/perform_spec.rb} +0 -226
  27. data/spec/rest_my_case/base/required_context_spec.rb +33 -0
  28. data/spec/rest_my_case/context/status_spec.rb +2 -2
  29. data/spec/rest_my_case/status_spec.rb +6 -6
  30. data/spec/support/required_context.rb +49 -0
  31. metadata +42 -24
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NDg4NmJlMDBmZjRiMzBlZjg4MWE1ZDUxMzc1MGQwZThlNmI3MmViNw==
5
- data.tar.gz: !binary |-
6
- Yjk3MjkxNzg0MzU4ODA4OTVhYmFmMGM4Zjg0ZWYyZWUxY2RmZTQ5NQ==
2
+ SHA1:
3
+ metadata.gz: a0f32849ac70e42eea144b0fc564245bd76afa3a
4
+ data.tar.gz: 78ed4d4e6833243cfce284be8ec5d22407084111
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NzhlMmU3MDMyYWQwYjQ4NjA0Y2VkMzhjZTJiOGNkNGE0YTEwOWE1MTRjYzg0
10
- OThkMzI3Njg0MzFlYzc2OWI4OGZjOWYxZjM3MGUyOTBkYzgzZGU5MDY5YjI2
11
- MTg1MTBmNjExZDY5M2MyNzVlZTRkMjVlNTQyY2U5MmY2NTk2Yjg=
12
- data.tar.gz: !binary |-
13
- ODIxZmI2NTNmZWU4NWEwNzE3ODUxY2E2N2EyZjA2ODNlMGY3ODA1OWQ3Y2I0
14
- MDNlZTExZjUzOGEyZTAyNjM4NDZhMGQ1ODgyNTYxN2JlYzNlODc2MGFhNDE2
15
- MmIzMTRhYjM0YWEzZDg4M2UyODQ4ZjY1OWUxY2M3ODQ0MWYyMzQ=
6
+ metadata.gz: c3725d52e75e29c2b9b3724ac38522a95a45a48e282a1560e4ce39245094fbc6718911378f67810c3055aff84eef9a7f57da215a0a5e0da982641da4f67e0878
7
+ data.tar.gz: 470adc3bfef70af304db5be018f7f57b5adb2d10eed7a17b325110148feccad8887d97fe258743e11f825982029bae19d9e2df5f4811fc430d0342f01cfa8cd1
data/README.md CHANGED
@@ -1,4 +1,332 @@
1
1
  # RestMyCase [![Code Climate](https://codeclimate.com/github/goncalvesjoao/rest_my_case/badges/gpa.svg)](https://codeclimate.com/github/goncalvesjoao/rest_my_case) [![Build Status](https://travis-ci.org/goncalvesjoao/rest_my_case.svg?branch=master)](https://travis-ci.org/goncalvesjoao/rest_my_case) [![Test Coverage](https://codeclimate.com/github/goncalvesjoao/rest_my_case/badges/coverage.svg)](https://codeclimate.com/github/goncalvesjoao/rest_my_case) [![Gem Version](https://badge.fury.io/rb/rest_my_case.svg)](http://badge.fury.io/rb/rest_my_case)
2
2
 
3
- Very light Ruby gem with everything you need in a "The Clean Architecture" use case scenario.
4
- Props to [@tdantas](https://github.com/tdantas) and [@junhanamaki](https://github.com/junhanamaki)
3
+ Light Ruby gem with everything you need in a "The Clean Architecture" use case scenario.
4
+
5
+ Many thanks to [@tdantas](https://github.com/tdantas) and [@junhanamaki](https://github.com/junhanamaki) and a shout-out to [@joaquimadraz](https://github.com/joaquimadraz) and his [compel](https://github.com/joaquimadraz/compel) ruby validations gem.
6
+
7
+ ---
8
+
9
+ ## 1) Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'rest_my_case'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install rest_my_case
22
+
23
+ ---
24
+
25
+ ## 2) Ideology
26
+ Your business logic goes into separated use cases...
27
+ ```ruby
28
+ class FindPost < RestMyCase::Base
29
+
30
+ def perform
31
+ context.post = Post.find(context.id)
32
+ end
33
+
34
+ end
35
+
36
+ class ArchivePost < RestMyCase::Base
37
+
38
+ depends FindPost
39
+
40
+ def perform
41
+ context.post.status = 'archived'
42
+
43
+ context.result = context.post.save
44
+ end
45
+
46
+ end
47
+ ```
48
+
49
+ web framework should only act as a bridge between the user and your business logic.
50
+ ```ruby
51
+ class PostsController < ApplicationController
52
+
53
+ def archive
54
+ @context = ArchivePost.perform id: params[:id]
55
+
56
+ if @context.result
57
+ redirect_to @context.post
58
+ else
59
+ render "archive" #view post.errors
60
+ end
61
+ end
62
+
63
+ end
64
+ ```
65
+
66
+ Ideally your business logic should be a ruby gem that can be tested independently from your framework.
67
+
68
+ Checkout this step by step tutorial: (WIP) on how to isolate your code into a ruby gem and connect it to your rails or sinatra api.
69
+
70
+ ---
71
+
72
+ ## 3) Basic usage
73
+
74
+ ```ruby
75
+ class BuildPost < RestMyCase::Base
76
+ def perform
77
+ puts context.id
78
+ puts context.post_attributes
79
+ end
80
+ end
81
+ ```
82
+
83
+ ```
84
+ irb> params = { id: 1, post: { title: 'my first post' } }
85
+ irb> context = BuildPost.perform id: params[:id], post_attributes: params[:post]
86
+ 1
87
+ {:title=>"my first post"}
88
+ irb> context.id
89
+ 1
90
+ ```
91
+
92
+ The Hash passed down to **BuildPost.perform** will be available through an instance method called **#context** that will return an OpenStruct object initialized with that Hash (see more in section 7).
93
+
94
+ Executing **BuildPost.perform** will instantiate your use case and all of its **dependencies**, build a **context** with the contents of **params**, run your use case (and its dependencies) with that context and return it at the end.
95
+
96
+ ## 3.1) Normal usage
97
+ Organize your use cases by single responsibilities and establish your use case flow through "dependencies".
98
+
99
+ ```ruby
100
+ class FindPost < RestMyCase::Base
101
+ def perform
102
+ context.post = Post.find(context.id)
103
+ end
104
+ end
105
+
106
+ class BuildPost < RestMyCase::Base
107
+ depends FindPost
108
+
109
+ def perform
110
+ context.post.assign_attributes context.post_attributes
111
+ end
112
+ end
113
+ ```
114
+ The class method **.depends** will make **BuildPost** dependent of **FindPost** which means that calling **BuildPost.perform** will run **FindPost#perform** first and **BuildPost#perform** last. Both use cases will share the same context.
115
+
116
+ ```
117
+ irb> params = { id: 1, post: { title: 'my first post' } }
118
+ irb> context = BuildPost.perform id: params[:id], post_attributes: params[:post]
119
+ irb> context.post.name
120
+ "my first post"
121
+ ```
122
+
123
+ ---
124
+
125
+ ## 4) Lifecycle
126
+
127
+ ## 4.1) Waiting to be implemented methods
128
+ Methods: **#setup**, **#perform**, **#rollback** and **#final**
129
+ ```ruby
130
+ class UseCase1 < RestMyCase::Base
131
+ def setup
132
+ puts 'UseCase1#setup'
133
+ end
134
+ def perform
135
+ puts 'UseCase1#perform'
136
+ error if context.should_fail
137
+ end
138
+ def rollback
139
+ puts 'UseCase1#rollback'
140
+ end
141
+ def final
142
+ puts 'UseCase1#final'
143
+ end
144
+ end
145
+ ```
146
+
147
+ ```
148
+ irb> UseCase1.perform #will print
149
+ "UseCase1#setup"
150
+ "UseCase1#perform"
151
+ "UseCase1#final"
152
+ ```
153
+
154
+ Method **#rollback** will be called after **#perform** and before **#final** if **#error** is invoked inside a **#setup** of **#perform** (see more in section 5).
155
+ ```
156
+ irb> UseCase1.perform(should_fail: true) #will print
157
+ "UseCase1#setup"
158
+ "UseCase1#perform"
159
+ "UseCase1#rollback"
160
+ "UseCase1#final"
161
+ ```
162
+
163
+ Method **#final** will run last and always, no matter how many times **#error** was called.
164
+
165
+ ---
166
+
167
+ ### 4.2) Dependencies
168
+ Default behaviour is to run your dependencies (**#setup**, **#perform**, **#rollback** and **#final**) methods, first.
169
+ ```ruby
170
+ class UseCase2 < RestMyCase::Base
171
+ def perform
172
+ puts 'UseCase2#perform'
173
+ end
174
+ end
175
+
176
+ class UseCase3 < RestMyCase::Base
177
+ def perform
178
+ puts 'UseCase3#perform'
179
+ end
180
+ end
181
+
182
+ class UseCase1 < RestMyCase::Base
183
+ depends UseCase2,
184
+ UseCase3
185
+
186
+ def perform
187
+ puts 'UseCase1#perform'
188
+ end
189
+ end
190
+ ```
191
+
192
+ ```
193
+ irb> UseCase1.perform #will print
194
+ "UseCase2#perform"
195
+ "UseCase3#perform"
196
+ "UseCase1#perform"
197
+ ```
198
+
199
+ See section 8 for more examples.
200
+
201
+ ---
202
+
203
+ ## 5) Flow control methods
204
+
205
+ Methods | Behaviour
206
+ ------- | ---------
207
+ **#abort** | Stops other remaining use cases from running and triggers **#rollback** on already executed use cases (in reverse order).
208
+ **#skip** | Will prevent **#perform** (of the use case that called **#skip**) from running and will not stop other use cases from running nor trigger a **#rollback** (only works by being used inside a **#setup** method).
209
+ **#error(error_message = '')** | Will do the same as **#abort** but will also push **error_message** to **#context.errors** array so you can track down what happen in what use case (see more in section 7).
210
+ **#invoke(*use_case_classes)** | Does the same as the class method **.depends** but executes the use cases on demand. Shares the context to them and if they call **#abort** on their side, the use case that **invoked** will also **abort**.
211
+
212
+ **#skip**, **#abort**, **#error** and **#invoke** have a "bang!" version that will raise a controlled exception, preventing the remaining lines of code from running.
213
+ ```ruby
214
+ class UseCase1 < RestMyCase::Base
215
+ def perform
216
+ puts 'before #error!'
217
+ error!
218
+ puts 'after #error!'
219
+ end
220
+ end
221
+ ```
222
+
223
+ ```
224
+ irb> UseCase1.perform #will print only
225
+ "before #error!"
226
+ ```
227
+
228
+ ---
229
+
230
+ ## 6) Configuration methods
231
+
232
+ Methods | Behaviour
233
+ ------- | ---------
234
+ **.depends(*use_case_classes)** | Adds the **use_case_classes** array to the use case's **dependencies** list, that will be executed by order before the actual use case (see more in section 4).
235
+ **.required_context(*attributes)** | WIP.
236
+ **.context_reader(*methods)** | Defines getter methods that return **context.send method**, to help reduce the **context.method** boilerplate.
237
+ **.context_writer(*methods)** | Defines setter methods that set **context.send "#{method}=", value**, to help reduce the **context.method = value** boilerplate.
238
+ **.context_accessor(*methods)** | Calls both **.context_reader** and **.context_writer** methods.
239
+ **.silence_dependencies_abort=** | If **false** once a dependency calls **#abort(!)** the next in line dependencies will not be called (and **#rollback** will be called in reverse order) but if **true** all dependencies will run no matter how many times **#abort(!)** was called (usefull when you want to run multiple validations (see more in section 9).
240
+
241
+ ---
242
+
243
+ ## 7) **#context** methods
244
+ The returning object is an instance of **RestMyCase::Context::Base** class that inherits from **OpenStruct** and implements the following methods:
245
+
246
+ Methods | Behaviour
247
+ ------- | ---------
248
+ **#attributes** | Alias to **#marshal_dump**, returns all of the context's stored data.
249
+ **#to_hash** | Serializes and unserializes **#attributes** turning any existing ruby objects into serialized strings.
250
+ **#valid?** | Checks if **#errors** is empty
251
+ **#ok?** | Alias to **#valid?**
252
+ **#success?** | Alias to **#ok?**
253
+ **#errors** | Array that gets 'pushed' with **{ message: error_message, class_name: UseCase.class.name }** (or **error_message** itself if **error_message** already a Hash) every time **UseCase#error(error_message)** is called.
254
+
255
+ If **defined?(ActiveModel)** is true, **ActiveModel::Serialization** will be included and in turn methods like **#to_json(options = {})** and **#serializable_hash(options = nil)** will become available.
256
+
257
+ ---
258
+
259
+ ### 8) Examples
260
+ If **UseCase1** depends on **UseCase2** and **UseCase3** in that respective order.
261
+
262
+ Running **UseCase1.perform** will pass down the context to each use case in the following manner:
263
+
264
+ #### 8.1) Given that no use case called the method(s) **#error(!)**
265
+ ```
266
+ UseCase2#setup -> UseCase3#setup -> UseCase1#setup ->
267
+ UseCase2#perform -> UseCase3#perform -> UseCase1#perform ->
268
+ UseCase2#final -> UseCase3#final -> UseCase1#final
269
+ ```
270
+
271
+ #### 8.2) Given that **UseCase3#setup** calls **#skip(!)**
272
+ ```
273
+ UseCase2#setup -> UseCase3#setup -> UseCase1#setup ->
274
+ UseCase2#perform -> UseCase1#perform ->
275
+ UseCase2#final -> UseCase3#final -> UseCase1#final
276
+ ```
277
+
278
+ #### 8.3) Given that **UseCase3#setup** calls **#error(!)**
279
+ ```
280
+ UseCase2#setup -> UseCase3#setup ->
281
+ UseCase3#rollback -> UseCase2#rollback ->
282
+ UseCase2#final -> UseCase3#final -> UseCase1#final
283
+ ```
284
+
285
+ #### 8.4) Given that **UseCase3#perform** calls **#error(!)**
286
+ ```
287
+ UseCase2#setup -> UseCase3#setup -> UseCase1#setup ->
288
+ UseCase2#perform -> UseCase3#perform ->
289
+ UseCase3#rollback -> UseCase2#rollback ->
290
+ UseCase2#final -> UseCase3#final -> UseCase1#final
291
+ ```
292
+
293
+ ---
294
+
295
+ ## 9) RestMyCase::Validator class
296
+ WIP
297
+
298
+ ---
299
+
300
+ ## 10) RestMyCase::Status module
301
+ ```ruby
302
+ class UseCase1 < RestMyCase::Base
303
+ include RestMyCase::Status
304
+ end
305
+ ```
306
+
307
+ Adds following methods:
308
+
309
+ Methods | Behaviour
310
+ ------- | ---------
311
+ **#context** | Returns an instance of **RestMyCase::Context::Status**
312
+ **#status** | Returns **context.status** (see more in section 10.1)
313
+ **#failure(status, error_message = nil)** | WIP
314
+
315
+ **#failure!** is also present and does the same as the other flow control "bang!" methods (see section 5).
316
+
317
+ ### 10.1) RestMyCase::Context::Status
318
+ WIP
319
+
320
+ ---
321
+
322
+ ## 11) RestMyCase::HttpStatus module (for seamless API integration)
323
+ ```ruby
324
+ class UseCase1 < RestMyCase::Base
325
+ include RestMyCase::HttpStatus
326
+ end
327
+ ```
328
+
329
+ Includes the module **RestMyCase::Status** and **#context** becomes an instance of **RestMyCase::Context::HttpStatus**.
330
+
331
+ ### 11.1) RestMyCase::Context::HttpStatus
332
+ WIP
@@ -9,6 +9,18 @@ module RestMyCase
9
9
  Judge::Base, DefenseAttorney::Base, RestMyCase::Base, Context::Base
10
10
  end
11
11
 
12
+ def self.required_context(*schema)
13
+ if schema.length == 1 && (schema[0].is_a?(Hash) || schema[0].is_a?(Array))
14
+ @required_context_schema = schema[0]
15
+ else
16
+ @required_context_schema = schema
17
+ end
18
+ end
19
+
20
+ def self.required_context_schema
21
+ @required_context_schema ||= {}
22
+ end
23
+
12
24
  def self.depends(*use_case_classes)
13
25
  dependencies.push(*use_case_classes)
14
26
  end
@@ -44,42 +56,56 @@ module RestMyCase
44
56
 
45
57
  ######################## INSTANCE METHODS BELLOW ###########################
46
58
 
47
- attr_reader :context, :dependent_use_case, :options
59
+ attr_reader :context, :options
48
60
 
49
61
  def initialize(context, dependent_use_case = nil)
50
- @options = {}
51
- @context = context
52
- @dependent_use_case = dependent_use_case
62
+ @context = context
63
+ @options = { dependent_use_case: dependent_use_case }
64
+
65
+ return unless dependent_use_case
66
+
67
+ @options[:silent_abort] = RestMyCase.get_config \
68
+ :silence_dependencies_abort, dependent_use_case.class
53
69
  end
54
70
 
55
- def setup; end
71
+ def setup; end
56
72
 
57
- def perform; end
73
+ def perform; end
58
74
 
59
75
  def rollback; end
60
76
 
61
77
  def final; end
62
78
 
63
79
  def invoke(*use_case_classes)
64
- trial_court.execute(use_case_classes, context.to_hash).context
80
+ self.class.trial_court.execute(use_case_classes, context.to_hash).context
65
81
  end
66
82
 
67
83
  def invoke!(*use_case_classes)
68
- trial_court.execute(use_case_classes, context).tap do |trial_case|
69
- abort! if trial_case.aborted
70
- end.context
84
+ trial_case = self.class.trial_court.execute(use_case_classes, context)
85
+
86
+ abort! if trial_case.aborted
87
+
88
+ trial_case.context
71
89
  end
72
90
 
73
91
  def abort
74
- silent_abort? ? dependent_use_case.abort : (options[:should_abort] = true)
92
+ if options[:silent_abort]
93
+ options[:dependent_use_case].abort
94
+ else
95
+ options[:should_abort] = true
96
+ end
75
97
  end
76
98
 
77
99
  def abort!
78
100
  abort && fail(Errors::Abort)
79
101
  end
80
102
 
81
- def error(error_data = '')
82
- error_data = { message: error_data } unless error_data.is_a?(Hash)
103
+ def error(error_message = '')
104
+ if error_message.is_a?(Hash)
105
+ error_data = error_message
106
+ else
107
+ error_data = { message: error_message }
108
+ end
83
109
 
84
110
  error_data[:class_name] = self.class.name
85
111
 
@@ -98,17 +124,16 @@ module RestMyCase
98
124
  skip && fail(Errors::Skip)
99
125
  end
100
126
 
101
- protected ######################## PROTECTED ###############################
127
+ def validate_context(schema = self.class.required_context_schema)
128
+ errors = context.validate_schema(schema)
102
129
 
103
- def trial_court
104
- self.class.trial_court
105
- end
130
+ error(context_errors: errors, message: 'invalid context') if errors
106
131
 
107
- def silent_abort?
108
- return false if dependent_use_case.nil?
132
+ Helpers.blank? errors
133
+ end
109
134
 
110
- RestMyCase.get_config \
111
- :silence_dependencies_abort, dependent_use_case.class
135
+ def validate_context!(schema = self.class.required_context)
136
+ validate_context(schema) && fail(Errors::Abort)
112
137
  end
113
138
 
114
139
  end
@@ -1,3 +1,6 @@
1
+ require 'rest_my_case/context/errors/base'
2
+ require 'rest_my_case/context/schema_validator/base'
3
+
1
4
  module RestMyCase
2
5
  module Context
3
6
 
@@ -11,10 +14,18 @@ module RestMyCase
11
14
  Errors::Base
12
15
  end
13
16
 
17
+ def self.schema_validator_class
18
+ SchemaValidator::Base
19
+ end
20
+
14
21
  def to_hash
15
22
  Marshal.load Marshal.dump(attributes)
16
23
  end
17
24
 
25
+ def validate_schema(schema)
26
+ self.class.schema_validator_class.new(self).validate(schema)
27
+ end
28
+
18
29
  def errors
19
30
  @errors ||= self.class.error_class.new(self)
20
31
  end
@@ -0,0 +1,27 @@
1
+ module RestMyCase
2
+ module Context
3
+ module SchemaValidator
4
+
5
+ class Base
6
+
7
+ def initialize(context)
8
+ @context = context
9
+ end
10
+
11
+ def validate(schema)
12
+ errors = {}
13
+
14
+ schema.each do |required_attribute|
15
+ if Helpers.blank?(@context.send(required_attribute))
16
+ errors[required_attribute] = 'is required'
17
+ end
18
+ end
19
+
20
+ Helpers.blank?(errors) ? nil : errors
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,36 @@
1
+ require 'compel'
2
+
3
+ module RestMyCase
4
+ module Context
5
+ module SchemaValidator
6
+
7
+ class Base
8
+
9
+ def initialize(context)
10
+ @context = context
11
+ end
12
+
13
+ def validate(schema)
14
+ result = ::Compel.run(@context, build_schema(schema))
15
+
16
+ result.valid? ? nil : result.errors
17
+ end
18
+
19
+ protected ###################### PROTECTED #############################
20
+
21
+ def build_schema(schema)
22
+ ::Compel.hash.keys \
23
+ schema.is_a?(Hash) ? schema : all_attributes_required(schema)
24
+ end
25
+
26
+ def all_attributes_required(schema)
27
+ {}.tap do |new_schema|
28
+ schema.each { |key| new_schema[key] = Compel.any.required }
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,5 @@
1
+ require 'rest_my_case/context/errors/status'
2
+
1
3
  module RestMyCase
2
4
  module Context
3
5
 
@@ -4,7 +4,7 @@ module RestMyCase
4
4
  class Base
5
5
 
6
6
  def initialize(trial_case)
7
- @trial_case = trial_case
7
+ @trial_case = trial_case
8
8
  @trial_case.use_cases = []
9
9
  end
10
10
 
@@ -1,18 +1,15 @@
1
+ require 'rest_my_case/context/http_status'
2
+
1
3
  module RestMyCase
2
4
 
3
5
  module HttpStatus
4
6
 
5
7
  include Status
6
8
 
7
- module ClassMethods
8
- def trial_court
9
- @trial_court ||= Trial::Court.new \
10
- Judge::Base, DefenseAttorney::Base, Base, Context::HttpStatus
11
- end
12
- end
13
-
14
9
  def self.included(parent_class)
15
- parent_class.extend ClassMethods
10
+ return unless parent_class.respond_to? :trial_court
11
+
12
+ parent_class.trial_court.context_class = Context::HttpStatus
16
13
  end
17
14
 
18
15
  end
@@ -4,8 +4,8 @@ module RestMyCase
4
4
  class Base
5
5
 
6
6
  def initialize(trial_case)
7
- @trial_case = trial_case
8
- @performed_use_cases = []
7
+ @trial_case = trial_case
8
+ @performed_use_cases = []
9
9
  @use_case_that_aborted = nil
10
10
  end
11
11
 
@@ -22,16 +22,21 @@ module RestMyCase
22
22
 
23
23
  def run_setup_methods
24
24
  @trial_case.use_cases.each do |use_case|
25
- break if method_setup_has_aborted use_case
25
+ break if method_aborts?(:setup, use_case)
26
26
  end
27
27
  end
28
28
 
29
29
  def run_perform_methods
30
- return nil if @use_case_that_aborted
31
-
32
30
  @trial_case.use_cases.each do |use_case|
33
- break if method_perform_has_aborted use_case
31
+ validate_context_aborts?(use_case)
32
+
33
+ next if use_case.options[:should_skip] || @use_case_that_aborted
34
+
35
+ @performed_use_cases.push use_case
36
+
37
+ method_aborts?(:perform, use_case)
34
38
  end
39
+
35
40
  end
36
41
 
37
42
  def run_rollback_methods
@@ -50,16 +55,16 @@ module RestMyCase
50
55
 
51
56
  private ########################### PRIVATE ##############################
52
57
 
53
- def method_setup_has_aborted(use_case)
54
- method_aborts?(:setup, use_case)
55
- end
56
-
57
- def method_perform_has_aborted(use_case)
58
- return false if use_case.options[:should_skip]
58
+ def validate_context_aborts?(use_case)
59
+ should_abort_before = use_case.options[:should_abort]
59
60
 
60
- @performed_use_cases.push use_case
61
+ use_case.validate_context
61
62
 
62
- method_aborts?(:perform, use_case)
63
+ if !should_abort_before && use_case.options[:should_abort]
64
+ @use_case_that_aborted = use_case
65
+ end
66
+ rescue Errors::Abort
67
+ @use_case_that_aborted = use_case
63
68
  end
64
69
 
65
70
  def method_aborts?(method_name, use_case)