servactory 1.5.1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +87 -50
- data/config/locales/en.yml +5 -5
- data/lib/servactory/base.rb +4 -4
- data/lib/servactory/configuration/factory.rb +6 -6
- data/lib/servactory/configuration/setup.rb +6 -6
- data/lib/servactory/context/callable.rb +21 -22
- data/lib/servactory/context/configuration.rb +6 -6
- data/lib/servactory/context/workspace/inputs.rb +13 -0
- data/lib/servactory/context/workspace.rb +9 -7
- data/lib/servactory/errors/base.rb +2 -1
- data/lib/servactory/errors/collection.rb +25 -0
- data/lib/servactory/errors/failure.rb +11 -1
- data/lib/servactory/errors/input_error.rb +17 -0
- data/lib/servactory/errors/internal_error.rb +15 -0
- data/lib/servactory/errors/output_error.rb +15 -0
- data/lib/servactory/{input_arguments → inputs}/checks/base.rb +3 -3
- data/lib/servactory/{input_arguments → inputs}/checks/errors.rb +1 -1
- data/lib/servactory/{input_arguments → inputs}/checks/inclusion.rb +7 -4
- data/lib/servactory/{input_arguments → inputs}/checks/must.rb +3 -3
- data/lib/servactory/{input_arguments → inputs}/checks/required.rb +2 -2
- data/lib/servactory/{input_arguments → inputs}/checks/type.rb +3 -3
- data/lib/servactory/{input_arguments → inputs}/collection.rb +1 -1
- data/lib/servactory/{input_arguments → inputs}/define_input_conflict.rb +1 -1
- data/lib/servactory/{input_arguments → inputs}/define_input_method.rb +1 -1
- data/lib/servactory/inputs/dsl.rb +36 -0
- data/lib/servactory/{input_arguments/input_argument.rb → inputs/input.rb} +13 -12
- data/lib/servactory/{input_arguments → inputs}/option.rb +5 -3
- data/lib/servactory/{input_arguments → inputs}/options_collection.rb +1 -1
- data/lib/servactory/{input_arguments → inputs}/tools/check.rb +5 -5
- data/lib/servactory/{input_arguments → inputs}/tools/check_errors.rb +1 -1
- data/lib/servactory/{input_arguments → inputs}/tools/find_unnecessary.rb +6 -6
- data/lib/servactory/{input_arguments → inputs}/tools/prepare.rb +5 -5
- data/lib/servactory/inputs/tools/rules.rb +46 -0
- data/lib/servactory/{input_arguments → inputs}/workbench.rb +8 -8
- data/lib/servactory/internals/checks/base.rb +17 -0
- data/lib/servactory/{internal_arguments → internals}/checks/type.rb +8 -8
- data/lib/servactory/{output_arguments → internals}/collection.rb +1 -1
- data/lib/servactory/internals/dsl.rb +33 -0
- data/lib/servactory/{internal_arguments/internal_argument.rb → internals/internal.rb} +2 -2
- data/lib/servactory/internals/tools/prepare.rb +60 -0
- data/lib/servactory/{internal_arguments → internals}/workbench.rb +5 -5
- data/lib/servactory/{make_methods → methods}/collection.rb +1 -1
- data/lib/servactory/methods/dsl.rb +33 -0
- data/lib/servactory/{make_methods/make_method.rb → methods/method.rb} +2 -2
- data/lib/servactory/{make_methods → methods}/workbench.rb +5 -5
- data/lib/servactory/outputs/checks/base.rb +17 -0
- data/lib/servactory/{output_arguments → outputs}/checks/type.rb +8 -8
- data/lib/servactory/{internal_arguments → outputs}/collection.rb +1 -1
- data/lib/servactory/outputs/dsl.rb +33 -0
- data/lib/servactory/{output_arguments/output_argument.rb → outputs/output.rb} +2 -2
- data/lib/servactory/{output_arguments → outputs}/tools/conflicts.rb +7 -7
- data/lib/servactory/outputs/tools/prepare.rb +62 -0
- data/lib/servactory/outputs/workbench.rb +31 -0
- data/lib/servactory/result.rb +4 -4
- data/lib/servactory/utils.rb +2 -0
- data/lib/servactory/version.rb +2 -2
- metadata +59 -46
- data/lib/servactory/context/workspace/error.rb +0 -19
- data/lib/servactory/context/workspace/errors.rb +0 -33
- data/lib/servactory/errors/input_argument_error.rb +0 -7
- data/lib/servactory/errors/internal_argument_error.rb +0 -7
- data/lib/servactory/errors/output_argument_error.rb +0 -7
- data/lib/servactory/input_arguments/dsl.rb +0 -36
- data/lib/servactory/input_arguments/tools/rules.rb +0 -43
- data/lib/servactory/inputs.rb +0 -9
- data/lib/servactory/internal_arguments/checks/base.rb +0 -17
- data/lib/servactory/internal_arguments/dsl.rb +0 -33
- data/lib/servactory/internal_arguments/tools/prepare.rb +0 -60
- data/lib/servactory/make_methods/dsl.rb +0 -33
- data/lib/servactory/output_arguments/checks/base.rb +0 -17
- data/lib/servactory/output_arguments/dsl.rb +0 -33
- data/lib/servactory/output_arguments/tools/prepare.rb +0 -62
- data/lib/servactory/output_arguments/workbench.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd3981fb61af74a47cc5d5279a51796d78527c2b4b16c3bdb69f7bd94e32932f
|
4
|
+
data.tar.gz: ca8ad9beca25c5dd04a9f7bb584ced4cef6b3f35d6d14c68c0d297ef817b8025
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e95bffde026a1b55bca088e15d86c2ec2b78ff4838be5f683c574e9ea1ed148a993a3075c4fb7b72493d3667b7280b4fe177edd748262bd77193425571aabb96
|
7
|
+
data.tar.gz: c41af274f2c6c858f29cef27f7b9d0b61ebf106712f9a55ca739782f2bbb2e12758c51a4271901505fdd81028ec435b52308244a2d581ee8c82841b768169b7f
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ A set of tools for building reliable services of any complexity.
|
|
5
5
|
[![Gem version](https://img.shields.io/gem/v/servactory?logo=rubygems&logoColor=fff)](https://rubygems.org/gems/servactory)
|
6
6
|
[![Release Date](https://img.shields.io/github/release-date/afuno/servactory)](https://github.com/afuno/servactory/releases)
|
7
7
|
|
8
|
-
##
|
8
|
+
## Table of contents
|
9
9
|
|
10
10
|
- [Requirements](#requirements)
|
11
11
|
- [Getting started](#getting-started)
|
@@ -16,18 +16,19 @@ A set of tools for building reliable services of any complexity.
|
|
16
16
|
- [Minimal example](#minimal-example)
|
17
17
|
- [Call](#call)
|
18
18
|
- [Result](#result)
|
19
|
-
- [Input
|
20
|
-
- [
|
21
|
-
- [
|
22
|
-
- [
|
23
|
-
- [
|
24
|
-
- [
|
25
|
-
- [Inclusion](#inclusion)
|
26
|
-
- [Must](#must)
|
27
|
-
- [Output
|
28
|
-
- [Internal
|
19
|
+
- [Input](#input)
|
20
|
+
- [Type](#option-type)
|
21
|
+
- [Required](#option-required)
|
22
|
+
- [Internal](#option-internal)
|
23
|
+
- [Internal name](#option-as)
|
24
|
+
- [Array](#option-array)
|
25
|
+
- [Inclusion](#option-inclusion)
|
26
|
+
- [Must](#option-must)
|
27
|
+
- [Output](#output)
|
28
|
+
- [Internal](#internal)
|
29
29
|
- [Make](#make)
|
30
30
|
- [Failures](#failures)
|
31
|
+
- [Inheritance](#inheritance)
|
31
32
|
- [I18n](#i18n)
|
32
33
|
- [Testing](#testing)
|
33
34
|
- [Thanks](#thanks)
|
@@ -69,9 +70,9 @@ As a first step, it is recommended to prepare the base class for further inherit
|
|
69
70
|
|
70
71
|
module ApplicationService
|
71
72
|
module Errors
|
72
|
-
class
|
73
|
-
class
|
74
|
-
class
|
73
|
+
class InputError < Servactory::Errors::InputError; end
|
74
|
+
class OutputError < Servactory::Errors::OutputError; end
|
75
|
+
class InternalError < Servactory::Errors::InternalError; end
|
75
76
|
|
76
77
|
class Failure < Servactory::Errors::Failure; end
|
77
78
|
end
|
@@ -86,9 +87,9 @@ end
|
|
86
87
|
module ApplicationService
|
87
88
|
class Base < Servactory::Base
|
88
89
|
configuration do
|
89
|
-
|
90
|
-
|
91
|
-
|
90
|
+
input_error_class ApplicationService::Errors::InputError
|
91
|
+
output_error_class ApplicationService::Errors::OutputError
|
92
|
+
internal_error_class ApplicationService::Errors::InternalError
|
92
93
|
|
93
94
|
failure_class ApplicationService::Errors::Failure
|
94
95
|
end
|
@@ -155,11 +156,45 @@ And then you can work with this result, for example, in this way:
|
|
155
156
|
Notification::SendJob.perform_later(service_result.user.id)
|
156
157
|
```
|
157
158
|
|
158
|
-
### Input
|
159
|
+
### Input
|
159
160
|
|
160
|
-
####
|
161
|
+
#### Option `type`
|
161
162
|
|
162
|
-
|
163
|
+
Always required to specify. May contain one or more classes.
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
class UsersService::Accept < ApplicationService::Base
|
167
|
+
input :user, type: User
|
168
|
+
|
169
|
+
# ...
|
170
|
+
end
|
171
|
+
```
|
172
|
+
|
173
|
+
```ruby
|
174
|
+
class ToggleService < ApplicationService::Base
|
175
|
+
input :flag, type: [TrueClass, FalseClass]
|
176
|
+
|
177
|
+
# ...
|
178
|
+
end
|
179
|
+
```
|
180
|
+
|
181
|
+
#### Option `required`
|
182
|
+
|
183
|
+
By default, `required` is set to `true`.
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
class UsersService::Create < ApplicationService::Base
|
187
|
+
input :first_name, type: String
|
188
|
+
input :middle_name, type: String, required: false
|
189
|
+
input :last_name, type: String
|
190
|
+
|
191
|
+
# ...
|
192
|
+
end
|
193
|
+
```
|
194
|
+
|
195
|
+
#### Option `internal`
|
196
|
+
|
197
|
+
By default, `internal` is set to `false`.
|
163
198
|
|
164
199
|
```ruby
|
165
200
|
class UsersService::Accept < ApplicationService::Base
|
@@ -175,10 +210,6 @@ class UsersService::Accept < ApplicationService::Base
|
|
175
210
|
end
|
176
211
|
```
|
177
212
|
|
178
|
-
#### As an internal argument
|
179
|
-
|
180
|
-
With this approach, all input attributes are available from `inputs` as well as directly from the context.
|
181
|
-
|
182
213
|
```ruby
|
183
214
|
class UsersService::Accept < ApplicationService::Base
|
184
215
|
input :user, type: User, internal: true
|
@@ -193,21 +224,7 @@ class UsersService::Accept < ApplicationService::Base
|
|
193
224
|
end
|
194
225
|
```
|
195
226
|
|
196
|
-
####
|
197
|
-
|
198
|
-
By default, all inputs are required. To make an input optional, specify `false` in the `required` option.
|
199
|
-
|
200
|
-
```ruby
|
201
|
-
class UsersService::Create < ApplicationService::Base
|
202
|
-
input :first_name, type: String
|
203
|
-
input :middle_name, type: String, required: false
|
204
|
-
input :last_name, type: String
|
205
|
-
|
206
|
-
# ...
|
207
|
-
end
|
208
|
-
```
|
209
|
-
|
210
|
-
#### As (internal name)
|
227
|
+
#### Option `as`
|
211
228
|
|
212
229
|
This option changes the name of the input within the service.
|
213
230
|
|
@@ -227,7 +244,9 @@ class NotificationService::Create < ApplicationService::Base
|
|
227
244
|
end
|
228
245
|
```
|
229
246
|
|
230
|
-
####
|
247
|
+
#### Option `array`
|
248
|
+
|
249
|
+
Using this option will mean that the input argument is an array, each element of which has the specified type.
|
231
250
|
|
232
251
|
```ruby
|
233
252
|
class PymentsService::Send < ApplicationService::Base
|
@@ -237,7 +256,7 @@ class PymentsService::Send < ApplicationService::Base
|
|
237
256
|
end
|
238
257
|
```
|
239
258
|
|
240
|
-
####
|
259
|
+
#### Option `inclusion`
|
241
260
|
|
242
261
|
```ruby
|
243
262
|
class EventService::Send < ApplicationService::Base
|
@@ -247,7 +266,7 @@ class EventService::Send < ApplicationService::Base
|
|
247
266
|
end
|
248
267
|
```
|
249
268
|
|
250
|
-
####
|
269
|
+
#### Option `must`
|
251
270
|
|
252
271
|
Sometimes there are cases that require the implementation of a specific input attribute check. In such cases `must` can help.
|
253
272
|
|
@@ -266,7 +285,7 @@ class PymentsService::Send < ApplicationService::Base
|
|
266
285
|
end
|
267
286
|
```
|
268
287
|
|
269
|
-
### Output
|
288
|
+
### Output
|
270
289
|
|
271
290
|
```ruby
|
272
291
|
class NotificationService::Create < ApplicationService::Base
|
@@ -284,7 +303,7 @@ class NotificationService::Create < ApplicationService::Base
|
|
284
303
|
end
|
285
304
|
```
|
286
305
|
|
287
|
-
### Internal
|
306
|
+
### Internal
|
288
307
|
|
289
308
|
```ruby
|
290
309
|
class NotificationService::Create < ApplicationService::Base
|
@@ -351,10 +370,6 @@ def process_result
|
|
351
370
|
end
|
352
371
|
```
|
353
372
|
|
354
|
-
#### Inheritance
|
355
|
-
|
356
|
-
Service inheritance is also supported.
|
357
|
-
|
358
373
|
### Failures
|
359
374
|
|
360
375
|
The methods that are used in `make` may fail. In order to more informatively provide information about this outside the service, the following methods were prepared.
|
@@ -367,7 +382,7 @@ make :check!
|
|
367
382
|
def check!
|
368
383
|
return if inputs.invoice_number.start_with?("AA")
|
369
384
|
|
370
|
-
fail!("Invalid invoice number")
|
385
|
+
fail!(message: "Invalid invoice number")
|
371
386
|
end
|
372
387
|
```
|
373
388
|
|
@@ -379,10 +394,32 @@ make :check!
|
|
379
394
|
def check!
|
380
395
|
return if inputs.invoice_number.start_with?("AA")
|
381
396
|
|
382
|
-
fail_input!(:invoice_number, "Invalid invoice number")
|
397
|
+
fail_input!(:invoice_number, message: "Invalid invoice number")
|
383
398
|
end
|
384
399
|
```
|
385
400
|
|
401
|
+
#### Metadata
|
402
|
+
|
403
|
+
```ruby
|
404
|
+
fail!(
|
405
|
+
message: "Invalid invoice number",
|
406
|
+
meta: {
|
407
|
+
invoice_number: inputs.invoice_number
|
408
|
+
}
|
409
|
+
)
|
410
|
+
```
|
411
|
+
|
412
|
+
```ruby
|
413
|
+
exception.detailed_message # => Invalid invoice number (ApplicationService::Errors::Failure)
|
414
|
+
exception.message # => Invalid invoice number
|
415
|
+
exception.type # => :fail
|
416
|
+
exception.meta # => {:invoice_number=>"BB-7650AE"}
|
417
|
+
```
|
418
|
+
|
419
|
+
### Inheritance
|
420
|
+
|
421
|
+
Inheritance between services is also supported.
|
422
|
+
|
386
423
|
## I18n
|
387
424
|
|
388
425
|
All texts are stored in the localization file. All texts can be changed or supplemented by new locales.
|
data/config/locales/en.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
en:
|
2
2
|
servactory:
|
3
|
-
|
3
|
+
inputs:
|
4
4
|
checks:
|
5
5
|
inclusion:
|
6
6
|
default_error: "[%{service_class_name}] Wrong value in `%{input_name}`, must be one of `%{input_inclusion}`"
|
@@ -20,14 +20,14 @@ en:
|
|
20
20
|
error: "[%{service_class_name}] Unexpected attributes: `%{unnecessary_attributes}`"
|
21
21
|
rules:
|
22
22
|
error: "[%{service_class_name}] Conflict in `%{input_name}` input options: `%{conflict_code}`"
|
23
|
-
|
23
|
+
internals:
|
24
24
|
checks:
|
25
25
|
type:
|
26
|
-
default_error: "[%{service_class_name}] Wrong type of internal
|
27
|
-
|
26
|
+
default_error: "[%{service_class_name}] Wrong type of internal attribute `%{internal_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
27
|
+
outputs:
|
28
28
|
checks:
|
29
29
|
type:
|
30
|
-
default_error: "[%{service_class_name}] Wrong type of output
|
30
|
+
default_error: "[%{service_class_name}] Wrong type of output attribute `%{output_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
31
31
|
tools:
|
32
32
|
conflicts:
|
33
33
|
error: "[%{service_class_name}] Conflict between internal and output attributes `%{overlapping_attributes}`"
|
data/lib/servactory/base.rb
CHANGED
@@ -4,10 +4,10 @@ module Servactory
|
|
4
4
|
class Base
|
5
5
|
include Configuration::DSL
|
6
6
|
include Context::DSL
|
7
|
-
include
|
8
|
-
include
|
9
|
-
include
|
10
|
-
include
|
7
|
+
include Inputs::DSL
|
8
|
+
include Internals::DSL
|
9
|
+
include Outputs::DSL
|
10
|
+
include Methods::DSL
|
11
11
|
|
12
12
|
private_class_method :new
|
13
13
|
end
|
@@ -3,16 +3,16 @@
|
|
3
3
|
module Servactory
|
4
4
|
module Configuration
|
5
5
|
class Factory
|
6
|
-
def
|
7
|
-
Servactory.configuration.
|
6
|
+
def input_error_class(input_error_class)
|
7
|
+
Servactory.configuration.input_error_class = input_error_class
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
Servactory.configuration.
|
10
|
+
def output_error_class(output_error_class)
|
11
|
+
Servactory.configuration.output_error_class = output_error_class
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
Servactory.configuration.
|
14
|
+
def internal_error_class(internal_error_class)
|
15
|
+
Servactory.configuration.internal_error_class = internal_error_class
|
16
16
|
end
|
17
17
|
|
18
18
|
def failure_class(failure_class)
|
@@ -3,15 +3,15 @@
|
|
3
3
|
module Servactory
|
4
4
|
module Configuration
|
5
5
|
class Setup
|
6
|
-
attr_accessor :
|
7
|
-
:
|
8
|
-
:
|
6
|
+
attr_accessor :input_error_class,
|
7
|
+
:internal_error_class,
|
8
|
+
:output_error_class,
|
9
9
|
:failure_class
|
10
10
|
|
11
11
|
def initialize
|
12
|
-
@
|
13
|
-
@
|
14
|
-
@
|
12
|
+
@input_error_class = Servactory::Errors::InputError
|
13
|
+
@internal_error_class = Servactory::Errors::InternalError
|
14
|
+
@output_error_class = Servactory::Errors::OutputError
|
15
15
|
|
16
16
|
@failure_class = Servactory::Errors::Failure
|
17
17
|
end
|
@@ -8,23 +8,23 @@ module Servactory
|
|
8
8
|
|
9
9
|
assign_data_with(arguments)
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
inputs_workbench.find_unnecessary!
|
12
|
+
inputs_workbench.check_rules!
|
13
|
+
outputs_workbench.find_conflicts_in!(
|
14
|
+
collection_of_internals: collection_of_internals
|
15
15
|
)
|
16
16
|
|
17
17
|
prepare_data
|
18
18
|
|
19
|
-
|
19
|
+
inputs_workbench.check!
|
20
20
|
|
21
|
-
|
21
|
+
methods_workbench.run!
|
22
22
|
|
23
23
|
context_store.context.raise_first_fail
|
24
24
|
|
25
25
|
Servactory::Result.prepare_for(
|
26
26
|
context: context_store.context,
|
27
|
-
|
27
|
+
collection_of_outputs: collection_of_outputs
|
28
28
|
)
|
29
29
|
end
|
30
30
|
|
@@ -33,21 +33,21 @@ module Servactory
|
|
33
33
|
|
34
34
|
assign_data_with(arguments)
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
inputs_workbench.find_unnecessary!
|
37
|
+
inputs_workbench.check_rules!
|
38
|
+
outputs_workbench.find_conflicts_in!(
|
39
|
+
collection_of_internals: collection_of_internals
|
40
40
|
)
|
41
41
|
|
42
42
|
prepare_data
|
43
43
|
|
44
|
-
|
44
|
+
inputs_workbench.check!
|
45
45
|
|
46
|
-
|
46
|
+
methods_workbench.run!
|
47
47
|
|
48
48
|
Servactory::Result.prepare_for(
|
49
49
|
context: context_store.context,
|
50
|
-
|
50
|
+
collection_of_outputs: collection_of_outputs
|
51
51
|
)
|
52
52
|
end
|
53
53
|
|
@@ -56,21 +56,20 @@ module Servactory
|
|
56
56
|
attr_reader :context_store
|
57
57
|
|
58
58
|
def assign_data_with(arguments)
|
59
|
-
|
59
|
+
inputs_workbench.assign(
|
60
60
|
context: context_store.context,
|
61
61
|
arguments: arguments
|
62
62
|
)
|
63
63
|
|
64
|
-
|
65
|
-
|
66
|
-
|
64
|
+
internals_workbench.assign(context: context_store.context)
|
65
|
+
outputs_workbench.assign(context: context_store.context)
|
66
|
+
methods_workbench.assign(context: context_store.context)
|
67
67
|
end
|
68
68
|
|
69
69
|
def prepare_data
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
internal_arguments_workbench.prepare # 3
|
70
|
+
inputs_workbench.prepare # 1
|
71
|
+
outputs_workbench.prepare # 2
|
72
|
+
internals_workbench.prepare # 3
|
74
73
|
end
|
75
74
|
end
|
76
75
|
end
|
@@ -3,16 +3,16 @@
|
|
3
3
|
module Servactory
|
4
4
|
module Context
|
5
5
|
class Configuration
|
6
|
-
def
|
7
|
-
Servactory.configuration.
|
6
|
+
def input_error_class(input_error_class)
|
7
|
+
Servactory.configuration.input_error_class = input_error_class
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
Servactory.configuration.
|
10
|
+
def output_error_class(output_error_class)
|
11
|
+
Servactory.configuration.output_error_class = output_error_class
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
Servactory.configuration.
|
14
|
+
def internal_error_class(internal_error_class)
|
15
|
+
Servactory.configuration.internal_error_class = internal_error_class
|
16
16
|
end
|
17
17
|
|
18
18
|
def failure_class(failure_class)
|
@@ -6,26 +6,28 @@ module Servactory
|
|
6
6
|
attr_reader :inputs
|
7
7
|
|
8
8
|
def errors
|
9
|
-
@errors ||= Errors.new
|
9
|
+
@errors ||= Servactory::Errors::Collection.new
|
10
10
|
end
|
11
11
|
|
12
12
|
def assign_inputs(inputs)
|
13
13
|
@inputs = inputs
|
14
14
|
end
|
15
15
|
|
16
|
-
def fail_input!(
|
17
|
-
raise Servactory.configuration.
|
18
|
-
|
16
|
+
def fail_input!(input_name, message:)
|
17
|
+
raise Servactory.configuration.input_error_class.new(
|
18
|
+
input_name: input_name,
|
19
|
+
message: message
|
20
|
+
)
|
19
21
|
end
|
20
22
|
|
21
|
-
def fail!(
|
22
|
-
errors <<
|
23
|
+
def fail!(message:, meta: nil)
|
24
|
+
errors << Servactory.configuration.failure_class.new(message: message, meta: meta)
|
23
25
|
end
|
24
26
|
|
25
27
|
def raise_first_fail
|
26
28
|
return if (tmp_errors = errors.for_fails.not_blank).empty?
|
27
29
|
|
28
|
-
raise
|
30
|
+
raise tmp_errors.first
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module Errors
|
5
|
+
class Collection
|
6
|
+
# NOTE: http://words.steveklabnik.com/beware-subclassing-ruby-core-classes
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@collection, :<<, :to_a, :filter, :reject, :empty?, :first
|
9
|
+
|
10
|
+
def initialize(collection = Set.new)
|
11
|
+
@collection = collection
|
12
|
+
end
|
13
|
+
|
14
|
+
def not_blank
|
15
|
+
Collection.new(reject(&:blank?))
|
16
|
+
end
|
17
|
+
|
18
|
+
def for_fails
|
19
|
+
filtered = filter { |error| error.is_a?(Failure) }
|
20
|
+
|
21
|
+
Collection.new(filtered)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -2,6 +2,16 @@
|
|
2
2
|
|
3
3
|
module Servactory
|
4
4
|
module Errors
|
5
|
-
class Failure <
|
5
|
+
class Failure < Base
|
6
|
+
attr_reader :message,
|
7
|
+
:meta
|
8
|
+
|
9
|
+
def initialize(message:, meta: nil)
|
10
|
+
@message = message
|
11
|
+
@meta = meta
|
12
|
+
|
13
|
+
super(message)
|
14
|
+
end
|
15
|
+
end
|
6
16
|
end
|
7
17
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module Errors
|
5
|
+
class InputError < Base
|
6
|
+
attr_reader :message,
|
7
|
+
:input_name
|
8
|
+
|
9
|
+
def initialize(message:, input_name: nil)
|
10
|
+
@message = message
|
11
|
+
@input_name = input_name&.to_sym
|
12
|
+
|
13
|
+
super(message)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Servactory
|
4
|
-
module
|
4
|
+
module Inputs
|
5
5
|
module Checks
|
6
6
|
class Base
|
7
7
|
protected
|
8
8
|
|
9
|
-
def add_error(message, **
|
10
|
-
message = message.call(**
|
9
|
+
def add_error(message, **attributes)
|
10
|
+
message = message.call(**attributes) if message.is_a?(Proc)
|
11
11
|
|
12
12
|
errors << message
|
13
13
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Servactory
|
4
|
-
module
|
4
|
+
module Inputs
|
5
5
|
module Checks
|
6
6
|
class Inclusion < Base
|
7
7
|
DEFAULT_MESSAGE = lambda do |service_class_name:, input:, value:|
|
8
8
|
I18n.t(
|
9
|
-
"servactory.
|
9
|
+
"servactory.inputs.checks.inclusion.default_error",
|
10
10
|
service_class_name: service_class_name,
|
11
11
|
input_name: input.name,
|
12
12
|
input_inclusion: input.inclusion[:in],
|
@@ -37,10 +37,13 @@ module Servactory
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def check
|
40
|
-
|
40
|
+
inclusion_in, message = @input.inclusion.values_at(:in, :message)
|
41
|
+
|
42
|
+
return if inclusion_in.nil?
|
43
|
+
return if inclusion_in.include?(@value)
|
41
44
|
|
42
45
|
add_error(
|
43
|
-
DEFAULT_MESSAGE,
|
46
|
+
message.presence || DEFAULT_MESSAGE,
|
44
47
|
service_class_name: @context.class.name,
|
45
48
|
input: @input,
|
46
49
|
value: @value
|