servactory 1.4.4 → 1.4.6
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.
- checksums.yaml +4 -4
- data/README.md +49 -19
- data/config/locales/en.yml +33 -0
- data/lib/servactory/context/callable.rb +23 -0
- data/lib/servactory/context/workspace/errors.rb +1 -1
- data/lib/servactory/input_arguments/checks/base.rb +1 -1
- data/lib/servactory/input_arguments/checks/errors.rb +1 -1
- data/lib/servactory/input_arguments/checks/inclusion.rb +10 -3
- data/lib/servactory/input_arguments/checks/must.rb +26 -12
- data/lib/servactory/input_arguments/checks/required.rb +8 -5
- data/lib/servactory/input_arguments/checks/type.rb +14 -4
- data/lib/servactory/input_arguments/define_input_conflict.rb +13 -0
- data/lib/servactory/input_arguments/define_input_method.rb +15 -0
- data/lib/servactory/input_arguments/input_argument.rb +48 -60
- data/lib/servactory/input_arguments/option.rb +22 -4
- data/lib/servactory/input_arguments/options_collection.rb +7 -3
- data/lib/servactory/input_arguments/tools/find_unnecessary.rb +7 -2
- data/lib/servactory/input_arguments/tools/rules.rb +8 -3
- data/lib/servactory/internal_arguments/checks/type.rb +7 -2
- data/lib/servactory/output_arguments/checks/type.rb +7 -2
- data/lib/servactory/output_arguments/tools/conflicts.rb +7 -3
- data/lib/servactory/result.rb +12 -1
- data/lib/servactory/version.rb +1 -1
- metadata +29 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 995ff46dfe5e3620a05d0bbe4b21f515de2b63e593f971e1ec906721cd4bfb6d
|
4
|
+
data.tar.gz: 9df30c884f28760025da0a9f1e68ccb12a42e5cea702602c086fd0b31212da62
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bf7a7a0b667c3dce0926747b36fa85dc7cb6452e54cf7a51367918f8530cd09996a0d21e5d19d0fc06bc91cdfa3c00f2f0a464b9816738b9ea935b88c0d997b
|
7
|
+
data.tar.gz: 8b29bf3059b7420492c63321737eca8b9f79deea94ce52dfb5dd203c70f0a8fecbbeb29b55e2eb73a687220f85cbb71a5bd85664cd5b45a404e2cbe7ed168a42
|
data/README.md
CHANGED
@@ -14,10 +14,13 @@ A set of tools for building reliable services of any complexity.
|
|
14
14
|
- [Preparation](#preparation)
|
15
15
|
- [Usage](#usage)
|
16
16
|
- [Minimal example](#minimal-example)
|
17
|
+
- [Call](#call)
|
18
|
+
- [Result](#result)
|
17
19
|
- [Input attributes](#input-attributes)
|
18
20
|
- [Isolated usage](#isolated-usage)
|
19
21
|
- [As an internal argument](#isolated-usage)
|
20
22
|
- [Optional inputs](#optional-inputs)
|
23
|
+
- [As (internal name)](#as-internal-name)
|
21
24
|
- [An array of specific values](#an-array-of-specific-values)
|
22
25
|
- [Inclusion](#inclusion)
|
23
26
|
- [Must](#must)
|
@@ -25,7 +28,7 @@ A set of tools for building reliable services of any complexity.
|
|
25
28
|
- [Internal attributes](#internal-attributes)
|
26
29
|
- [Stage](#stage)
|
27
30
|
- [Failures](#failures)
|
28
|
-
|
31
|
+
- [I18n](#i18n)
|
29
32
|
- [Testing](#testing)
|
30
33
|
- [Thanks](#thanks)
|
31
34
|
- [Contributing](#contributing)
|
@@ -111,6 +114,47 @@ end
|
|
111
114
|
|
112
115
|
[More examples](https://github.com/afuno/servactory/tree/main/examples/usual)
|
113
116
|
|
117
|
+
### Call
|
118
|
+
|
119
|
+
Services can only be called via `.call` and `.call!` methods.
|
120
|
+
|
121
|
+
The `.call` method will only fail if it catches an exception in the input arguments.
|
122
|
+
Internal and output attributes, as well as methods for failures - all this will be collected in the result.
|
123
|
+
|
124
|
+
The `.call!` method will fail if it catches any exception.
|
125
|
+
|
126
|
+
#### Via .call
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
UsersService::Accept.call(user: User.first)
|
130
|
+
```
|
131
|
+
|
132
|
+
#### Via .call!
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
UsersService::Accept.call!(user: User.first)
|
136
|
+
```
|
137
|
+
|
138
|
+
### Result
|
139
|
+
|
140
|
+
All services have the result of their work. For example, in case of success this call:
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
service_result = UsersService::Accept.call!(user: User.first)
|
144
|
+
```
|
145
|
+
|
146
|
+
Will return this:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
#<Servactory::Result:0x0000000107ad9e88 @user="...">
|
150
|
+
```
|
151
|
+
|
152
|
+
And then you can work with this result, for example, in this way:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
Notification::SendJob.perform_later(service_result.user.id)
|
156
|
+
```
|
157
|
+
|
114
158
|
### Input attributes
|
115
159
|
|
116
160
|
#### Isolated usage
|
@@ -163,7 +207,7 @@ class UsersService::Create < ApplicationService::Base
|
|
163
207
|
end
|
164
208
|
```
|
165
209
|
|
166
|
-
#### As
|
210
|
+
#### As (internal name)
|
167
211
|
|
168
212
|
This option changes the name of the input within the service.
|
169
213
|
|
@@ -346,25 +390,11 @@ def check!
|
|
346
390
|
end
|
347
391
|
```
|
348
392
|
|
349
|
-
|
350
|
-
|
351
|
-
All services have the result of their work. For example, in case of success this call:
|
352
|
-
|
353
|
-
```ruby
|
354
|
-
service_result = NotificationService::Create.call!(user: User.first)
|
355
|
-
```
|
356
|
-
|
357
|
-
Will return this:
|
393
|
+
## I18n
|
358
394
|
|
359
|
-
|
360
|
-
#<Servactory::Result:0x0000000112c00748 @notification=...>
|
361
|
-
```
|
362
|
-
|
363
|
-
And then you can work with this result, for example, in this way:
|
395
|
+
All texts are stored in the localization file. All texts can be changed or supplemented by new locales.
|
364
396
|
|
365
|
-
|
366
|
-
Notification::SendJob.perform_later(service_result.notification.id)
|
367
|
-
```
|
397
|
+
[See en.yml file](https://github.com/afuno/servactory/tree/main/config/locales/en.yml)
|
368
398
|
|
369
399
|
## Testing
|
370
400
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
en:
|
2
|
+
servactory:
|
3
|
+
input_arguments:
|
4
|
+
checks:
|
5
|
+
inclusion:
|
6
|
+
default_error: "[%{service_class_name}] Wrong value in `%{input_name}`, must be one of `%{input_inclusion}`"
|
7
|
+
must:
|
8
|
+
default_error: "[%{service_class_name}] Input `%{input_name}` must \"%{code}\""
|
9
|
+
syntax_error: "[%{service_class_name}] Syntax error inside `%{code}` of `%{input_name}` input"
|
10
|
+
required:
|
11
|
+
default_error:
|
12
|
+
default: "[%{service_class_name}] Required input `%{input_name}` is missing"
|
13
|
+
for_array: "[%{service_class_name}] Required element in input array `%{input_name}` is missing"
|
14
|
+
type:
|
15
|
+
default_error:
|
16
|
+
default: "[%{service_class_name}] Wrong type of input `%{input_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
17
|
+
for_array: "[%{service_class_name}] Wrong type in input array `%{input_name}`, expected `%{expected_type}`"
|
18
|
+
tools:
|
19
|
+
find_unnecessary:
|
20
|
+
error: "[%{service_class_name}] Unexpected attributes: `%{unnecessary_attributes}`"
|
21
|
+
rules:
|
22
|
+
error: "[%{service_class_name}] Conflict in `%{input_name}` input options: `%{conflict_code}`"
|
23
|
+
internal_arguments:
|
24
|
+
checks:
|
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:
|
28
|
+
checks:
|
29
|
+
type:
|
30
|
+
default_error: "[%{service_class_name}] Wrong type of output argument `%{output_argument_name}`, expected `%{expected_type}`, got `%{given_type}`"
|
31
|
+
tools:
|
32
|
+
conflicts:
|
33
|
+
error: "[%{service_class_name}] Conflict between internal and output attributes `%{overlapping_attributes}`"
|
@@ -28,6 +28,29 @@ module Servactory
|
|
28
28
|
)
|
29
29
|
end
|
30
30
|
|
31
|
+
def call(arguments = {}) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
32
|
+
@context_store = Store.new(self)
|
33
|
+
|
34
|
+
assign_data_with(arguments)
|
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
|
40
|
+
)
|
41
|
+
|
42
|
+
prepare_data
|
43
|
+
|
44
|
+
input_arguments_workbench.check!
|
45
|
+
|
46
|
+
stage_handyman.run_methods!
|
47
|
+
|
48
|
+
Servactory::Result.prepare_for(
|
49
|
+
context: context_store.context,
|
50
|
+
collection_of_output_arguments: collection_of_output_arguments
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
31
54
|
private
|
32
55
|
|
33
56
|
attr_reader :context_store
|
@@ -6,7 +6,7 @@ module Servactory
|
|
6
6
|
class Errors
|
7
7
|
# NOTE: http://words.steveklabnik.com/beware-subclassing-ruby-core-classes
|
8
8
|
extend Forwardable
|
9
|
-
def_delegators :@collection, :<<, :filter, :reject, :empty?, :first
|
9
|
+
def_delegators :@collection, :<<, :to_a, :filter, :reject, :empty?, :first
|
10
10
|
|
11
11
|
def initialize(collection = Set.new)
|
12
12
|
@collection = collection
|
@@ -4,8 +4,14 @@ module Servactory
|
|
4
4
|
module InputArguments
|
5
5
|
module Checks
|
6
6
|
class Inclusion < Base
|
7
|
-
DEFAULT_MESSAGE = lambda do |service_class_name:, input:|
|
8
|
-
|
7
|
+
DEFAULT_MESSAGE = lambda do |service_class_name:, input:, value:|
|
8
|
+
I18n.t(
|
9
|
+
"servactory.input_arguments.checks.inclusion.default_error",
|
10
|
+
service_class_name: service_class_name,
|
11
|
+
input_name: input.name,
|
12
|
+
input_inclusion: input.inclusion[:in],
|
13
|
+
value: value
|
14
|
+
)
|
9
15
|
end
|
10
16
|
|
11
17
|
private_constant :DEFAULT_MESSAGE
|
@@ -36,7 +42,8 @@ module Servactory
|
|
36
42
|
add_error(
|
37
43
|
DEFAULT_MESSAGE,
|
38
44
|
service_class_name: @context.class.name,
|
39
|
-
input: @input
|
45
|
+
input: @input,
|
46
|
+
value: @value
|
40
47
|
)
|
41
48
|
end
|
42
49
|
end
|
@@ -4,12 +4,28 @@ module Servactory
|
|
4
4
|
module InputArguments
|
5
5
|
module Checks
|
6
6
|
class Must < Base
|
7
|
-
DEFAULT_MESSAGE = lambda do |service_class_name:, input:, code:|
|
8
|
-
|
9
|
-
"must
|
7
|
+
DEFAULT_MESSAGE = lambda do |service_class_name:, input:, value:, code:|
|
8
|
+
I18n.t(
|
9
|
+
"servactory.input_arguments.checks.must.default_error",
|
10
|
+
service_class_name: service_class_name,
|
11
|
+
input_name: input.name,
|
12
|
+
value: value,
|
13
|
+
code: code
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
SYNTAX_ERROR_MESSAGE = lambda do |service_class_name:, input:, value:, code:, exception_message:|
|
18
|
+
I18n.t(
|
19
|
+
"servactory.input_arguments.checks.must.syntax_error",
|
20
|
+
service_class_name: service_class_name,
|
21
|
+
input_name: input.name,
|
22
|
+
value: value,
|
23
|
+
code: code,
|
24
|
+
exception_message: exception_message
|
25
|
+
)
|
10
26
|
end
|
11
27
|
|
12
|
-
private_constant :DEFAULT_MESSAGE
|
28
|
+
private_constant :DEFAULT_MESSAGE, :SYNTAX_ERROR_MESSAGE
|
13
29
|
|
14
30
|
def self.check(context:, input:, value:, check_key:, check_options:)
|
15
31
|
return unless should_be_checked_for?(input, check_key)
|
@@ -39,9 +55,10 @@ module Servactory
|
|
39
55
|
next if message.blank?
|
40
56
|
|
41
57
|
add_error(
|
42
|
-
|
58
|
+
message,
|
43
59
|
service_class_name: @context.class.name,
|
44
60
|
input: @input,
|
61
|
+
value: @value,
|
45
62
|
code: code
|
46
63
|
)
|
47
64
|
end
|
@@ -58,16 +75,13 @@ module Servactory
|
|
58
75
|
|
59
76
|
message.presence || DEFAULT_MESSAGE
|
60
77
|
rescue StandardError => e
|
61
|
-
message_text =
|
62
|
-
"[#{@context.class.name}] Syntax error inside `#{code}` of `#{@input.name}` input"
|
63
|
-
|
64
|
-
puts "#{message_text}: #{e}"
|
65
|
-
|
66
78
|
add_error(
|
67
|
-
|
79
|
+
SYNTAX_ERROR_MESSAGE,
|
68
80
|
service_class_name: @context.class.name,
|
69
81
|
input: @input,
|
70
|
-
|
82
|
+
value: @value,
|
83
|
+
code: code,
|
84
|
+
exception_message: e.message
|
71
85
|
)
|
72
86
|
end
|
73
87
|
end
|
@@ -5,11 +5,14 @@ module Servactory
|
|
5
5
|
module Checks
|
6
6
|
class Required < Base
|
7
7
|
DEFAULT_MESSAGE = lambda do |service_class_name:, input:, value:|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
i18n_key = "servactory.input_arguments.checks.required.default_error."
|
9
|
+
i18n_key += input.array? && value.present? ? "for_array" : "default"
|
10
|
+
|
11
|
+
I18n.t(
|
12
|
+
i18n_key,
|
13
|
+
service_class_name: service_class_name,
|
14
|
+
input_name: input.name
|
15
|
+
)
|
13
16
|
end
|
14
17
|
|
15
18
|
private_constant :DEFAULT_MESSAGE
|
@@ -13,12 +13,22 @@ module Servactory
|
|
13
13
|
elsif array_message.is_a?(String) && array_message.present?
|
14
14
|
array_message
|
15
15
|
else
|
16
|
-
|
16
|
+
I18n.t(
|
17
|
+
"servactory.input_arguments.checks.type.default_error.for_array",
|
18
|
+
service_class_name: service_class_name,
|
19
|
+
input_name: input.name,
|
20
|
+
expected_type: expected_type,
|
21
|
+
given_type: given_type
|
22
|
+
)
|
17
23
|
end
|
18
24
|
else
|
19
|
-
|
20
|
-
"
|
21
|
-
|
25
|
+
I18n.t(
|
26
|
+
"servactory.input_arguments.checks.type.default_error.default",
|
27
|
+
service_class_name: service_class_name,
|
28
|
+
input_name: input.name,
|
29
|
+
expected_type: expected_type,
|
30
|
+
given_type: given_type
|
31
|
+
)
|
22
32
|
end
|
23
33
|
end
|
24
34
|
|
@@ -55,22 +55,19 @@ module Servactory
|
|
55
55
|
name: :required,
|
56
56
|
input: self,
|
57
57
|
check_class: Servactory::InputArguments::Checks::Required,
|
58
|
-
define_input_methods:
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
return :required_vs_default if required? && default_value_present?
|
72
|
-
RUBY
|
73
|
-
end,
|
58
|
+
define_input_methods: [
|
59
|
+
DefineInputMethod.new(
|
60
|
+
name: :required?,
|
61
|
+
content: ->(value:) { Servactory::Utils.boolean?(value[:is]) }
|
62
|
+
),
|
63
|
+
DefineInputMethod.new(
|
64
|
+
name: :optional?,
|
65
|
+
content: ->(value:) { !Servactory::Utils.boolean?(value[:is]) }
|
66
|
+
)
|
67
|
+
],
|
68
|
+
define_input_conflicts: [
|
69
|
+
DefineInputConflict.new(content: -> { return :required_vs_default if required? && default_value_present? })
|
70
|
+
],
|
74
71
|
need_for_checks: true,
|
75
72
|
value_key: :is,
|
76
73
|
value_fallback: true,
|
@@ -95,13 +92,12 @@ module Servactory
|
|
95
92
|
name: :default,
|
96
93
|
input: self,
|
97
94
|
check_class: Servactory::InputArguments::Checks::Type,
|
98
|
-
define_input_methods:
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end,
|
95
|
+
define_input_methods: [
|
96
|
+
DefineInputMethod.new(
|
97
|
+
name: :default_value_present?,
|
98
|
+
content: ->(value:) { !value.nil? }
|
99
|
+
)
|
100
|
+
],
|
105
101
|
need_for_checks: true,
|
106
102
|
value_fallback: nil,
|
107
103
|
with_advanced_mode: false,
|
@@ -114,19 +110,16 @@ module Servactory
|
|
114
110
|
name: :array,
|
115
111
|
input: self,
|
116
112
|
check_class: Servactory::InputArguments::Checks::Type,
|
117
|
-
define_input_methods:
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
return :array_vs_inclusion if array? && inclusion_present?
|
128
|
-
RUBY
|
129
|
-
end,
|
113
|
+
define_input_methods: [
|
114
|
+
DefineInputMethod.new(
|
115
|
+
name: :array?,
|
116
|
+
content: ->(value:) { Servactory::Utils.boolean?(value[:is]) }
|
117
|
+
)
|
118
|
+
],
|
119
|
+
define_input_conflicts: [
|
120
|
+
DefineInputConflict.new(content: -> { return :array_vs_array if array? && types.include?(Array) }),
|
121
|
+
DefineInputConflict.new(content: -> { return :array_vs_inclusion if array? && inclusion_present? })
|
122
|
+
],
|
130
123
|
need_for_checks: false,
|
131
124
|
value_key: :is,
|
132
125
|
value_fallback: false,
|
@@ -139,13 +132,12 @@ module Servactory
|
|
139
132
|
name: :inclusion,
|
140
133
|
input: self,
|
141
134
|
check_class: Servactory::InputArguments::Checks::Inclusion,
|
142
|
-
define_input_methods:
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
end,
|
135
|
+
define_input_methods: [
|
136
|
+
DefineInputMethod.new(
|
137
|
+
name: :inclusion_present?,
|
138
|
+
content: ->(value:) { value[:in].is_a?(Array) && value[:in].present? }
|
139
|
+
)
|
140
|
+
],
|
149
141
|
need_for_checks: true,
|
150
142
|
value_key: :in,
|
151
143
|
value_fallback: nil,
|
@@ -158,13 +150,12 @@ module Servactory
|
|
158
150
|
name: :must,
|
159
151
|
input: self,
|
160
152
|
check_class: Servactory::InputArguments::Checks::Must,
|
161
|
-
define_input_methods:
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
end,
|
153
|
+
define_input_methods: [
|
154
|
+
DefineInputMethod.new(
|
155
|
+
name: :must_present?,
|
156
|
+
content: ->(value:) { value.present? }
|
157
|
+
)
|
158
|
+
],
|
168
159
|
need_for_checks: true,
|
169
160
|
value_key: :is,
|
170
161
|
value_fallback: nil,
|
@@ -178,13 +169,12 @@ module Servactory
|
|
178
169
|
name: :internal,
|
179
170
|
input: self,
|
180
171
|
check_class: nil,
|
181
|
-
define_input_methods:
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
end,
|
172
|
+
define_input_methods: [
|
173
|
+
DefineInputMethod.new(
|
174
|
+
name: :internal?,
|
175
|
+
content: ->(value:) { Servactory::Utils.boolean?(value[:is]) }
|
176
|
+
)
|
177
|
+
],
|
188
178
|
need_for_checks: false,
|
189
179
|
value_key: :is,
|
190
180
|
value_fallback: false,
|
@@ -197,9 +187,7 @@ module Servactory
|
|
197
187
|
end
|
198
188
|
|
199
189
|
def conflict_code
|
200
|
-
|
201
|
-
|
202
|
-
nil
|
190
|
+
collection_of_options.defined_conflict_code
|
203
191
|
end
|
204
192
|
|
205
193
|
def with_conflicts?
|
@@ -9,7 +9,8 @@ module Servactory
|
|
9
9
|
|
10
10
|
attr_reader :name,
|
11
11
|
:check_class,
|
12
|
-
:
|
12
|
+
:define_input_methods,
|
13
|
+
:define_input_conflicts,
|
13
14
|
:need_for_checks,
|
14
15
|
:value_key,
|
15
16
|
:value
|
@@ -24,13 +25,14 @@ module Servactory
|
|
24
25
|
original_value: nil,
|
25
26
|
value_key: nil,
|
26
27
|
define_input_methods: nil,
|
27
|
-
|
28
|
+
define_input_conflicts: nil,
|
28
29
|
with_advanced_mode: true,
|
29
30
|
**options
|
30
31
|
) # do
|
31
32
|
@name = name.to_sym
|
32
33
|
@check_class = check_class
|
33
|
-
@
|
34
|
+
@define_input_methods = define_input_methods
|
35
|
+
@define_input_conflicts = define_input_conflicts
|
34
36
|
@need_for_checks = need_for_checks
|
35
37
|
@value_key = value_key
|
36
38
|
|
@@ -41,7 +43,7 @@ module Servactory
|
|
41
43
|
with_advanced_mode: with_advanced_mode
|
42
44
|
)
|
43
45
|
|
44
|
-
input
|
46
|
+
prepare_input_methods_for(input)
|
45
47
|
end
|
46
48
|
# rubocop:enable Metrics/MethodLength
|
47
49
|
|
@@ -73,6 +75,22 @@ module Servactory
|
|
73
75
|
DEFAULT_VALUE.call(key: value_key, value: value)
|
74
76
|
end
|
75
77
|
end
|
78
|
+
|
79
|
+
def prepare_input_methods_for(input)
|
80
|
+
input.instance_eval(define_input_methods_template) if define_input_methods_template.present?
|
81
|
+
end
|
82
|
+
|
83
|
+
def define_input_methods_template
|
84
|
+
return if @define_input_methods.blank?
|
85
|
+
|
86
|
+
@define_input_methods_template ||= @define_input_methods.map do |define_input_method|
|
87
|
+
<<-RUBY
|
88
|
+
def #{define_input_method.name}
|
89
|
+
#{define_input_method.content.call(value: @value)}
|
90
|
+
end
|
91
|
+
RUBY
|
92
|
+
end.join("\n")
|
93
|
+
end
|
76
94
|
end
|
77
95
|
end
|
78
96
|
end
|
@@ -5,7 +5,7 @@ module Servactory
|
|
5
5
|
class OptionsCollection
|
6
6
|
# NOTE: http://words.steveklabnik.com/beware-subclassing-ruby-core-classes
|
7
7
|
extend Forwardable
|
8
|
-
def_delegators :@collection, :<<, :filter, :each, :map
|
8
|
+
def_delegators :@collection, :<<, :filter, :each, :map, :flat_map
|
9
9
|
|
10
10
|
def initialize(*)
|
11
11
|
@collection = Set.new
|
@@ -27,8 +27,12 @@ module Servactory
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
|
30
|
+
def defined_conflict_code
|
31
|
+
flat_map do |option|
|
32
|
+
option.define_input_conflicts&.map do |define_input_conflict|
|
33
|
+
define_input_conflict.content.call
|
34
|
+
end
|
35
|
+
end.reject(&:blank?).first
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
@@ -17,8 +17,13 @@ module Servactory
|
|
17
17
|
def check!
|
18
18
|
return if unnecessary_attributes.empty?
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
message_text = I18n.t(
|
21
|
+
"servactory.input_arguments.tools.find_unnecessary.error",
|
22
|
+
service_class_name: @context.class.name,
|
23
|
+
unnecessary_attributes: unnecessary_attributes.join(", ")
|
24
|
+
)
|
25
|
+
|
26
|
+
raise Servactory.configuration.input_argument_error_class, message_text
|
22
27
|
end
|
23
28
|
|
24
29
|
private
|
@@ -28,9 +28,14 @@ module Servactory
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def raise_error_for(input_argument)
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
message_text = I18n.t(
|
32
|
+
"servactory.input_arguments.tools.rules.error",
|
33
|
+
service_class_name: @context.class.name,
|
34
|
+
input_name: input_argument.name,
|
35
|
+
conflict_code: input_argument.conflict_code
|
36
|
+
)
|
37
|
+
|
38
|
+
raise Servactory.configuration.input_argument_error_class, message_text
|
34
39
|
end
|
35
40
|
end
|
36
41
|
end
|
@@ -5,8 +5,13 @@ module Servactory
|
|
5
5
|
module Checks
|
6
6
|
class Type < Base
|
7
7
|
DEFAULT_MESSAGE = lambda do |service_class_name:, internal_argument:, expected_type:, given_type:|
|
8
|
-
|
9
|
-
"
|
8
|
+
I18n.t(
|
9
|
+
"servactory.internal_arguments.checks.type.default_error",
|
10
|
+
service_class_name: service_class_name,
|
11
|
+
internal_argument_name: internal_argument.name,
|
12
|
+
expected_type: expected_type,
|
13
|
+
given_type: given_type
|
14
|
+
)
|
10
15
|
end
|
11
16
|
|
12
17
|
private_constant :DEFAULT_MESSAGE
|
@@ -5,8 +5,13 @@ module Servactory
|
|
5
5
|
module Checks
|
6
6
|
class Type < Base
|
7
7
|
DEFAULT_MESSAGE = lambda do |service_class_name:, output_argument:, expected_type:, given_type:|
|
8
|
-
|
9
|
-
"
|
8
|
+
I18n.t(
|
9
|
+
"servactory.output_arguments.checks.type.default_error",
|
10
|
+
service_class_name: service_class_name,
|
11
|
+
output_argument_name: output_argument.name,
|
12
|
+
expected_type: expected_type,
|
13
|
+
given_type: given_type
|
14
|
+
)
|
10
15
|
end
|
11
16
|
|
12
17
|
private_constant :DEFAULT_MESSAGE
|
@@ -17,9 +17,13 @@ module Servactory
|
|
17
17
|
def check!
|
18
18
|
return if overlapping_attributes.empty?
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
message_text = I18n.t(
|
21
|
+
"servactory.output_arguments.tools.conflicts.error",
|
22
|
+
service_class_name: @context.class.name,
|
23
|
+
overlapping_attributes: overlapping_attributes.join(", ")
|
24
|
+
)
|
25
|
+
|
26
|
+
raise Servactory.configuration.output_argument_error_class, message_text
|
23
27
|
end
|
24
28
|
|
25
29
|
private
|
data/lib/servactory/result.rb
CHANGED
@@ -9,13 +9,24 @@ module Servactory
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def prepare_for(context:, collection_of_output_arguments:)
|
12
|
+
prepare_outputs_with(context: context, collection_of_output_arguments: collection_of_output_arguments)
|
13
|
+
prepare_statuses_with(context: context)
|
14
|
+
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def prepare_outputs_with(context:, collection_of_output_arguments:)
|
12
19
|
collection_of_output_arguments.each do |output|
|
13
20
|
self.class.attr_reader(:"#{output.name}")
|
14
21
|
|
15
22
|
instance_variable_set(:"@#{output.name}", context.instance_variable_get(:"@#{output.name}"))
|
16
23
|
end
|
24
|
+
end
|
17
25
|
|
18
|
-
|
26
|
+
def prepare_statuses_with(context:)
|
27
|
+
define_singleton_method(:errors) { context.errors }
|
28
|
+
define_singleton_method(:success?) { context.errors.empty? }
|
29
|
+
define_singleton_method(:failure?) { !context.errors.empty? }
|
19
30
|
end
|
20
31
|
end
|
21
32
|
end
|
data/lib/servactory/version.rb
CHANGED
metadata
CHANGED
@@ -1,57 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: servactory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anton Sokolov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-05-
|
11
|
+
date: 2023-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '7.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '7.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: i18n
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '1.13'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '1.13'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: zeitwerk
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
48
|
-
type: :
|
47
|
+
version: '2.6'
|
48
|
+
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '2.6'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: pry
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0.14'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '13.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '13.0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rbs
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -159,6 +173,7 @@ extra_rdoc_files: []
|
|
159
173
|
files:
|
160
174
|
- README.md
|
161
175
|
- Rakefile
|
176
|
+
- config/locales/en.yml
|
162
177
|
- lib/servactory.rb
|
163
178
|
- lib/servactory/base.rb
|
164
179
|
- lib/servactory/configuration/dsl.rb
|
@@ -183,6 +198,8 @@ files:
|
|
183
198
|
- lib/servactory/input_arguments/checks/required.rb
|
184
199
|
- lib/servactory/input_arguments/checks/type.rb
|
185
200
|
- lib/servactory/input_arguments/collection.rb
|
201
|
+
- lib/servactory/input_arguments/define_input_conflict.rb
|
202
|
+
- lib/servactory/input_arguments/define_input_method.rb
|
186
203
|
- lib/servactory/input_arguments/dsl.rb
|
187
204
|
- lib/servactory/input_arguments/input_argument.rb
|
188
205
|
- lib/servactory/input_arguments/option.rb
|