servactory 1.5.1 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +87 -50
  3. data/config/locales/en.yml +5 -5
  4. data/lib/servactory/base.rb +4 -4
  5. data/lib/servactory/configuration/factory.rb +6 -6
  6. data/lib/servactory/configuration/setup.rb +6 -6
  7. data/lib/servactory/context/callable.rb +21 -22
  8. data/lib/servactory/context/configuration.rb +6 -6
  9. data/lib/servactory/context/workspace/inputs.rb +13 -0
  10. data/lib/servactory/context/workspace.rb +9 -7
  11. data/lib/servactory/errors/base.rb +2 -1
  12. data/lib/servactory/errors/collection.rb +25 -0
  13. data/lib/servactory/errors/failure.rb +11 -1
  14. data/lib/servactory/errors/input_error.rb +17 -0
  15. data/lib/servactory/errors/internal_error.rb +15 -0
  16. data/lib/servactory/errors/output_error.rb +15 -0
  17. data/lib/servactory/{input_arguments → inputs}/checks/base.rb +3 -3
  18. data/lib/servactory/{input_arguments → inputs}/checks/errors.rb +1 -1
  19. data/lib/servactory/{input_arguments → inputs}/checks/inclusion.rb +7 -4
  20. data/lib/servactory/{input_arguments → inputs}/checks/must.rb +3 -3
  21. data/lib/servactory/{input_arguments → inputs}/checks/required.rb +2 -2
  22. data/lib/servactory/{input_arguments → inputs}/checks/type.rb +3 -3
  23. data/lib/servactory/{input_arguments → inputs}/collection.rb +1 -1
  24. data/lib/servactory/{input_arguments → inputs}/define_input_conflict.rb +1 -1
  25. data/lib/servactory/{input_arguments → inputs}/define_input_method.rb +1 -1
  26. data/lib/servactory/inputs/dsl.rb +36 -0
  27. data/lib/servactory/{input_arguments/input_argument.rb → inputs/input.rb} +13 -12
  28. data/lib/servactory/{input_arguments → inputs}/option.rb +5 -3
  29. data/lib/servactory/{input_arguments → inputs}/options_collection.rb +1 -1
  30. data/lib/servactory/{input_arguments → inputs}/tools/check.rb +5 -5
  31. data/lib/servactory/{input_arguments → inputs}/tools/check_errors.rb +1 -1
  32. data/lib/servactory/{input_arguments → inputs}/tools/find_unnecessary.rb +6 -6
  33. data/lib/servactory/{input_arguments → inputs}/tools/prepare.rb +5 -5
  34. data/lib/servactory/inputs/tools/rules.rb +46 -0
  35. data/lib/servactory/{input_arguments → inputs}/workbench.rb +8 -8
  36. data/lib/servactory/internals/checks/base.rb +17 -0
  37. data/lib/servactory/{internal_arguments → internals}/checks/type.rb +8 -8
  38. data/lib/servactory/{output_arguments → internals}/collection.rb +1 -1
  39. data/lib/servactory/internals/dsl.rb +33 -0
  40. data/lib/servactory/{internal_arguments/internal_argument.rb → internals/internal.rb} +2 -2
  41. data/lib/servactory/internals/tools/prepare.rb +60 -0
  42. data/lib/servactory/{internal_arguments → internals}/workbench.rb +5 -5
  43. data/lib/servactory/{make_methods → methods}/collection.rb +1 -1
  44. data/lib/servactory/methods/dsl.rb +33 -0
  45. data/lib/servactory/{make_methods/make_method.rb → methods/method.rb} +2 -2
  46. data/lib/servactory/{make_methods → methods}/workbench.rb +5 -5
  47. data/lib/servactory/outputs/checks/base.rb +17 -0
  48. data/lib/servactory/{output_arguments → outputs}/checks/type.rb +8 -8
  49. data/lib/servactory/{internal_arguments → outputs}/collection.rb +1 -1
  50. data/lib/servactory/outputs/dsl.rb +33 -0
  51. data/lib/servactory/{output_arguments/output_argument.rb → outputs/output.rb} +2 -2
  52. data/lib/servactory/{output_arguments → outputs}/tools/conflicts.rb +7 -7
  53. data/lib/servactory/outputs/tools/prepare.rb +62 -0
  54. data/lib/servactory/outputs/workbench.rb +31 -0
  55. data/lib/servactory/result.rb +4 -4
  56. data/lib/servactory/utils.rb +2 -0
  57. data/lib/servactory/version.rb +2 -2
  58. metadata +59 -46
  59. data/lib/servactory/context/workspace/error.rb +0 -19
  60. data/lib/servactory/context/workspace/errors.rb +0 -33
  61. data/lib/servactory/errors/input_argument_error.rb +0 -7
  62. data/lib/servactory/errors/internal_argument_error.rb +0 -7
  63. data/lib/servactory/errors/output_argument_error.rb +0 -7
  64. data/lib/servactory/input_arguments/dsl.rb +0 -36
  65. data/lib/servactory/input_arguments/tools/rules.rb +0 -43
  66. data/lib/servactory/inputs.rb +0 -9
  67. data/lib/servactory/internal_arguments/checks/base.rb +0 -17
  68. data/lib/servactory/internal_arguments/dsl.rb +0 -33
  69. data/lib/servactory/internal_arguments/tools/prepare.rb +0 -60
  70. data/lib/servactory/make_methods/dsl.rb +0 -33
  71. data/lib/servactory/output_arguments/checks/base.rb +0 -17
  72. data/lib/servactory/output_arguments/dsl.rb +0 -33
  73. data/lib/servactory/output_arguments/tools/prepare.rb +0 -62
  74. data/lib/servactory/output_arguments/workbench.rb +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77f19d5b6971cbec1d9f9c5861d14cfe511d4bdcd7d4636349909d2fc66136cd
4
- data.tar.gz: a0db50ba89379e4de2155b3b3d4b574bf0284aa23ef672071f1f0afa74ec5fb5
3
+ metadata.gz: dd3981fb61af74a47cc5d5279a51796d78527c2b4b16c3bdb69f7bd94e32932f
4
+ data.tar.gz: ca8ad9beca25c5dd04a9f7bb584ced4cef6b3f35d6d14c68c0d297ef817b8025
5
5
  SHA512:
6
- metadata.gz: 33720d025d61d2874b17181a5aa6d9f74ac060f1bb606da70495426c431afc1fb0e9d4ffdb8575a389a9d675fa0a900ef96a769df6653cc478d2df27176e894a
7
- data.tar.gz: 7e2ec6b1c657b943154e2f41ca7b43fe45fb77bc172664811a48a6575e6459ae154759f800ce59d1b179f3ff760a0f8ebf6dd97f4a3eb67f78d094e9cf55870b
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
- ## Contents
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 attributes](#input-attributes)
20
- - [Isolated usage](#isolated-usage)
21
- - [As an internal argument](#isolated-usage)
22
- - [Optional inputs](#optional-inputs)
23
- - [As (internal name)](#as-internal-name)
24
- - [An array of specific values](#an-array-of-specific-values)
25
- - [Inclusion](#inclusion)
26
- - [Must](#must)
27
- - [Output attributes](#output-attributes)
28
- - [Internal attributes](#internal-attributes)
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 InputArgumentError < Servactory::Errors::InputArgumentError; end
73
- class OutputArgumentError < Servactory::Errors::OutputArgumentError; end
74
- class InternalArgumentError < Servactory::Errors::InternalArgumentError; end
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
- input_argument_error_class ApplicationService::Errors::InputArgumentError
90
- output_argument_error_class ApplicationService::Errors::OutputArgumentError
91
- internal_argument_error_class ApplicationService::Errors::InternalArgumentError
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 attributes
159
+ ### Input
159
160
 
160
- #### Isolated usage
161
+ #### Option `type`
161
162
 
162
- With this approach, all input attributes are available only from `inputs`. This is default behaviour.
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
- #### Optional inputs
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
- #### An array of specific values
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
- #### Inclusion
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
- #### Must
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 attributes
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 attributes
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.
@@ -1,6 +1,6 @@
1
1
  en:
2
2
  servactory:
3
- input_arguments:
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
- internal_arguments:
23
+ internals:
24
24
  checks:
25
25
  type:
26
- default_error: "[%{service_class_name}] Wrong type of internal argument `%{internal_argument_name}`, expected `%{expected_type}`, got `%{given_type}`"
27
- output_arguments:
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 argument `%{output_argument_name}`, expected `%{expected_type}`, got `%{given_type}`"
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}`"
@@ -4,10 +4,10 @@ module Servactory
4
4
  class Base
5
5
  include Configuration::DSL
6
6
  include Context::DSL
7
- include InputArguments::DSL
8
- include InternalArguments::DSL
9
- include OutputArguments::DSL
10
- include MakeMethods::DSL
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 input_argument_error_class(input_argument_error_class)
7
- Servactory.configuration.input_argument_error_class = input_argument_error_class
6
+ def input_error_class(input_error_class)
7
+ Servactory.configuration.input_error_class = input_error_class
8
8
  end
9
9
 
10
- def output_argument_error_class(output_argument_error_class)
11
- Servactory.configuration.output_argument_error_class = output_argument_error_class
10
+ def output_error_class(output_error_class)
11
+ Servactory.configuration.output_error_class = output_error_class
12
12
  end
13
13
 
14
- def internal_argument_error_class(internal_argument_error_class)
15
- Servactory.configuration.internal_argument_error_class = internal_argument_error_class
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 :input_argument_error_class,
7
- :internal_argument_error_class,
8
- :output_argument_error_class,
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
- @input_argument_error_class = Servactory::Errors::InputArgumentError
13
- @internal_argument_error_class = Servactory::Errors::InternalArgumentError
14
- @output_argument_error_class = Servactory::Errors::OutputArgumentError
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
- input_arguments_workbench.find_unnecessary!
12
- input_arguments_workbench.check_rules!
13
- output_arguments_workbench.find_conflicts_in!(
14
- collection_of_internal_arguments: collection_of_internal_arguments
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
- input_arguments_workbench.check!
19
+ inputs_workbench.check!
20
20
 
21
- make_methods_workbench.run!
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
- collection_of_output_arguments: collection_of_output_arguments
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
- input_arguments_workbench.find_unnecessary!
37
- input_arguments_workbench.check_rules!
38
- output_arguments_workbench.find_conflicts_in!(
39
- collection_of_internal_arguments: collection_of_internal_arguments
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
- input_arguments_workbench.check!
44
+ inputs_workbench.check!
45
45
 
46
- make_methods_workbench.run!
46
+ methods_workbench.run!
47
47
 
48
48
  Servactory::Result.prepare_for(
49
49
  context: context_store.context,
50
- collection_of_output_arguments: collection_of_output_arguments
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
- input_arguments_workbench.assign(
59
+ inputs_workbench.assign(
60
60
  context: context_store.context,
61
61
  arguments: arguments
62
62
  )
63
63
 
64
- internal_arguments_workbench.assign(context: context_store.context)
65
- output_arguments_workbench.assign(context: context_store.context)
66
- make_methods_workbench.assign(context: context_store.context)
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
- input_arguments_workbench.prepare # 1
71
-
72
- output_arguments_workbench.prepare # 2
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 input_argument_error_class(input_argument_error_class)
7
- Servactory.configuration.input_argument_error_class = input_argument_error_class
6
+ def input_error_class(input_error_class)
7
+ Servactory.configuration.input_error_class = input_error_class
8
8
  end
9
9
 
10
- def output_argument_error_class(output_argument_error_class)
11
- Servactory.configuration.output_argument_error_class = output_argument_error_class
10
+ def output_error_class(output_error_class)
11
+ Servactory.configuration.output_error_class = output_error_class
12
12
  end
13
13
 
14
- def internal_argument_error_class(internal_argument_error_class)
15
- Servactory.configuration.internal_argument_error_class = internal_argument_error_class
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)
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Context
5
+ module Workspace
6
+ class Inputs
7
+ def initialize(**)
8
+ # NOTE: Look at the file `lib/servactory/inputs/tools/prepare.rb`
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -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!(input_attribute_name, message)
17
- raise Servactory.configuration.input_argument_error_class,
18
- Error.new(type: :input, attribute_name: input_attribute_name, message: message).message
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!(error)
22
- errors << Error.new(type: :fail, message: error)
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 Servactory.configuration.failure_class, tmp_errors.first.message
30
+ raise tmp_errors.first
29
31
  end
30
32
  end
31
33
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Servactory
4
4
  module Errors
5
- class Base < StandardError; end
5
+ class Base < StandardError
6
+ end
6
7
  end
7
8
  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 < Servactory::Errors::Base; end
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
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Errors
5
+ class InternalError < Base
6
+ attr_reader :message
7
+
8
+ def initialize(message:)
9
+ @message = message
10
+
11
+ super(message)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Errors
5
+ class OutputError < Base
6
+ attr_reader :message
7
+
8
+ def initialize(message:)
9
+ @message = message
10
+
11
+ super(message)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Servactory
4
- module InputArguments
4
+ module Inputs
5
5
  module Checks
6
6
  class Base
7
7
  protected
8
8
 
9
- def add_error(message, **arguments)
10
- message = message.call(**arguments) if message.is_a?(Proc)
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,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Servactory
4
- module InputArguments
4
+ module Inputs
5
5
  module Checks
6
6
  class Errors
7
7
  # NOTE: http://words.steveklabnik.com/beware-subclassing-ruby-core-classes
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Servactory
4
- module InputArguments
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.input_arguments.checks.inclusion.default_error",
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
- return if @input.inclusion[:in].include?(@value)
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