servactory 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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