servactory 1.1.0 → 1.3.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.
- checksums.yaml +4 -4
- data/README.md +79 -10
- data/lib/servactory/context/dsl.rb +10 -8
- data/lib/servactory/input_arguments/checks/inclusion.rb +1 -1
- data/lib/servactory/input_arguments/checks/must.rb +6 -7
- data/lib/servactory/input_arguments/checks/required.rb +1 -1
- data/lib/servactory/input_arguments/checks/type.rb +10 -2
- data/lib/servactory/input_arguments/input_argument.rb +21 -8
- data/lib/servactory/input_arguments/tools/check.rb +10 -5
- data/lib/servactory/input_arguments/tools/prepare.rb +7 -3
- data/lib/servactory/internal_arguments/internal_argument.rb +2 -2
- data/lib/servactory/internal_arguments/tools/prepare.rb +5 -3
- data/lib/servactory/output_arguments/output_argument.rb +3 -3
- data/lib/servactory/output_arguments/tools/prepare.rb +8 -4
- data/lib/servactory/stage/dsl.rb +2 -2
- data/lib/servactory/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e9766f87f647b0873a6671d88811141a77b571fb15ac5ee6b10b78e2e5696ca6
|
4
|
+
data.tar.gz: c36ee73abad2d9241f6b48190cbf3351fe8c9c40bc7cb9bdfdfb09c04e5d05f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11b27258c9a302cb989eed03fe4f1325c03855f58fd3a79b6cad7a3846fa8e9395f780fe0d9a2dd30c9b044d4e98df4677857c93c275f9bfe8780d6ebefe5d5e
|
7
|
+
data.tar.gz: 57800e68b8c8bece089513dcf0b0ff8da6ab2efb33a4d4a694b11995dae51b7dd0496b1b0f4b6c0ba403db5c6037432e43371d68bea5b56bb05844d98fb36e8e
|
data/README.md
CHANGED
@@ -81,36 +81,105 @@ class SendService < ApplicationService::Base
|
|
81
81
|
end
|
82
82
|
```
|
83
83
|
|
84
|
-
###
|
84
|
+
### Input attributes
|
85
|
+
|
86
|
+
#### Isolated usage
|
87
|
+
|
88
|
+
With this approach, all input attributes are available only from `inputs`.
|
85
89
|
|
86
90
|
```ruby
|
87
|
-
class
|
91
|
+
class UserService::Accept < ApplicationService::Base
|
88
92
|
input :user, type: User
|
89
93
|
|
90
|
-
stage { make :
|
94
|
+
stage { make :accept! }
|
91
95
|
|
92
96
|
private
|
93
97
|
|
94
|
-
def
|
95
|
-
|
98
|
+
def accept!
|
99
|
+
inputs.user.accept!
|
96
100
|
end
|
97
101
|
end
|
98
102
|
```
|
99
103
|
|
100
|
-
|
104
|
+
#### As an internal argument
|
105
|
+
|
106
|
+
With this approach, all input attributes are available from `inputs` as well as directly from the context.
|
101
107
|
|
102
108
|
```ruby
|
103
|
-
class
|
109
|
+
class UserService::Accept < ApplicationService::Base
|
110
|
+
input :user, type: User, internal: true
|
111
|
+
|
112
|
+
stage { make :accept! }
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def accept!
|
117
|
+
user.accept!
|
118
|
+
end
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
### Output attributes
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
class NotificationService::Create < ApplicationService::Base
|
104
126
|
input :user, type: User
|
105
127
|
|
106
128
|
output :notification, type: Notification
|
107
129
|
|
108
|
-
stage { make :
|
130
|
+
stage { make :create_notification! }
|
109
131
|
|
110
132
|
private
|
111
133
|
|
112
|
-
def
|
113
|
-
self.notification = Notification.create!
|
134
|
+
def create_notification!
|
135
|
+
self.notification = Notification.create!(user: inputs.user)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
### Internal attributes
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
class NotificationService::Create < ApplicationService::Base
|
144
|
+
input :user, type: User
|
145
|
+
|
146
|
+
internal :inviter, type: User
|
147
|
+
|
148
|
+
output :notification, type: Notification
|
149
|
+
|
150
|
+
stage do
|
151
|
+
make :assign_inviter
|
152
|
+
make :create_notification!
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
def assign_inviter
|
158
|
+
self.inviter = user.inviter
|
159
|
+
end
|
160
|
+
|
161
|
+
def create_notification!
|
162
|
+
self.notification = Notification.create!(user: inputs.user, inviter:)
|
114
163
|
end
|
115
164
|
end
|
116
165
|
```
|
166
|
+
|
167
|
+
### Result
|
168
|
+
|
169
|
+
All services have the result of their work. For example, in case of success this call:
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
service_result = NotificationService::Create.call!(user: User.first)
|
173
|
+
```
|
174
|
+
|
175
|
+
Will return this:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
#<Servactory::Result:0x0000000112c00748 @notification=...>
|
179
|
+
```
|
180
|
+
|
181
|
+
And then you can work with this result, for example, in this way:
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
Notification::SendJob.perform_later(service_result.notification.id)
|
185
|
+
```
|
@@ -15,7 +15,9 @@ module Servactory
|
|
15
15
|
|
16
16
|
input_arguments_workbench.find_unnecessary!
|
17
17
|
input_arguments_workbench.check_rules!
|
18
|
-
output_arguments_workbench.find_conflicts_in!(
|
18
|
+
output_arguments_workbench.find_conflicts_in!(
|
19
|
+
collection_of_internal_arguments: collection_of_internal_arguments
|
20
|
+
)
|
19
21
|
|
20
22
|
prepare_data
|
21
23
|
|
@@ -25,7 +27,7 @@ module Servactory
|
|
25
27
|
|
26
28
|
Servactory::Result.prepare_for(
|
27
29
|
context: context_store.context,
|
28
|
-
collection_of_output_arguments:
|
30
|
+
collection_of_output_arguments: collection_of_output_arguments
|
29
31
|
)
|
30
32
|
end
|
31
33
|
|
@@ -34,10 +36,10 @@ module Servactory
|
|
34
36
|
attr_reader :context_store
|
35
37
|
|
36
38
|
def assign_data_with(arguments)
|
37
|
-
input_arguments_workbench.assign(context: context_store.context, arguments:) # 1
|
38
|
-
internal_arguments_workbench.assign(context: context_store.context)
|
39
|
-
output_arguments_workbench.assign(context: context_store.context)
|
40
|
-
stage_handyman&.assign(context: context_store.context)
|
39
|
+
input_arguments_workbench.assign(context: context_store.context, arguments: arguments) # 1
|
40
|
+
internal_arguments_workbench.assign(context: context_store.context) # 2
|
41
|
+
output_arguments_workbench.assign(context: context_store.context) # 3
|
42
|
+
stage_handyman&.assign(context: context_store.context) # 4
|
41
43
|
end
|
42
44
|
|
43
45
|
def prepare_data
|
@@ -47,10 +49,10 @@ module Servactory
|
|
47
49
|
internal_arguments_workbench.prepare # 3
|
48
50
|
end
|
49
51
|
|
50
|
-
def configuration(&)
|
52
|
+
def configuration(&block)
|
51
53
|
context_configuration = Servactory::Context::Configuration.new
|
52
54
|
|
53
|
-
context_configuration.instance_eval(&)
|
55
|
+
context_configuration.instance_eval(&block)
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|
@@ -13,7 +13,7 @@ module Servactory
|
|
13
13
|
def self.check(context:, input:, value:, check_key:, **)
|
14
14
|
return unless should_be_checked_for?(input, check_key)
|
15
15
|
|
16
|
-
new(context
|
16
|
+
new(context: context, input: input, value: value).check
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.should_be_checked_for?(input, check_key)
|
@@ -14,7 +14,7 @@ module Servactory
|
|
14
14
|
def self.check(context:, input:, value:, check_key:, check_options:)
|
15
15
|
return unless should_be_checked_for?(input, check_key)
|
16
16
|
|
17
|
-
new(context
|
17
|
+
new(context: context, input: input, value: value, check_options: check_options).check
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.should_be_checked_for?(input, check_key)
|
@@ -32,7 +32,7 @@ module Servactory
|
|
32
32
|
@check_options = check_options
|
33
33
|
end
|
34
34
|
|
35
|
-
def check
|
35
|
+
def check # rubocop:disable Metrics/MethodLength
|
36
36
|
@check_options.each do |code, options|
|
37
37
|
message = call_or_fetch_message_from(code, options)
|
38
38
|
|
@@ -42,7 +42,7 @@ module Servactory
|
|
42
42
|
DEFAULT_MESSAGE,
|
43
43
|
service_class_name: @context.class.name,
|
44
44
|
input: @input,
|
45
|
-
code:
|
45
|
+
code: code
|
46
46
|
)
|
47
47
|
end
|
48
48
|
|
@@ -57,16 +57,15 @@ module Servactory
|
|
57
57
|
return if check.call(value: @value)
|
58
58
|
|
59
59
|
message.presence || DEFAULT_MESSAGE
|
60
|
-
rescue StandardError =>
|
60
|
+
rescue StandardError => _e
|
61
61
|
message_text =
|
62
|
-
"[#{@context.class.name}] Syntax error inside `#{code}` of "
|
63
|
-
"`#{@input.name}` input: [#{e.class}] #{e.message}"
|
62
|
+
"[#{@context.class.name}] Syntax error inside `#{code}` of `#{@input.name}` input"
|
64
63
|
|
65
64
|
add_error(
|
66
65
|
message_text,
|
67
66
|
service_class_name: @context.class.name,
|
68
67
|
input: @input,
|
69
|
-
code:
|
68
|
+
code: code
|
70
69
|
)
|
71
70
|
end
|
72
71
|
end
|
@@ -17,7 +17,7 @@ module Servactory
|
|
17
17
|
def self.check(context:, input:, value:, **)
|
18
18
|
return unless should_be_checked_for?(input)
|
19
19
|
|
20
|
-
new(context
|
20
|
+
new(context: context, input: input, value: value).check
|
21
21
|
end
|
22
22
|
|
23
23
|
def self.should_be_checked_for?(input)
|
@@ -6,7 +6,15 @@ module Servactory
|
|
6
6
|
class Type < Base
|
7
7
|
DEFAULT_MESSAGE = lambda do |service_class_name:, input:, expected_type:, given_type:|
|
8
8
|
if input.array?
|
9
|
-
|
9
|
+
array_message = input.array[:message]
|
10
|
+
|
11
|
+
if array_message.is_a?(Proc)
|
12
|
+
array_message.call(input: input, expected_type: expected_type)
|
13
|
+
elsif array_message.is_a?(String) && array_message.present?
|
14
|
+
array_message
|
15
|
+
else
|
16
|
+
"[#{service_class_name}] Wrong type in input array `#{input.name}`, expected `#{expected_type}`"
|
17
|
+
end
|
10
18
|
else
|
11
19
|
"[#{service_class_name}] Wrong type of input `#{input.name}`, " \
|
12
20
|
"expected `#{expected_type}`, " \
|
@@ -19,7 +27,7 @@ module Servactory
|
|
19
27
|
def self.check(context:, input:, value:, check_key:, check_options:)
|
20
28
|
return unless should_be_checked_for?(input, value, check_key)
|
21
29
|
|
22
|
-
new(context
|
30
|
+
new(context: context, input: input, value: value, types: check_options).check
|
23
31
|
end
|
24
32
|
|
25
33
|
def self.should_be_checked_for?(input, value, check_key)
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module Servactory
|
4
4
|
module InputArguments
|
5
5
|
class InputArgument
|
6
|
+
ARRAY_DEFAULT_VALUE = ->(is: false, message: nil) { { is: is, message: message } }
|
7
|
+
|
6
8
|
attr_reader :name,
|
7
9
|
:types,
|
8
10
|
:inclusion,
|
@@ -18,7 +20,7 @@ module Servactory
|
|
18
20
|
|
19
21
|
@inclusion = options.fetch(:inclusion, nil)
|
20
22
|
@must = options.fetch(:must, nil)
|
21
|
-
@array = options.fetch(:array,
|
23
|
+
@array = prepare_advanced_for(options.fetch(:array, ARRAY_DEFAULT_VALUE.call))
|
22
24
|
@required = options.fetch(:required, true)
|
23
25
|
@internal = options.fetch(:internal, false)
|
24
26
|
@default = options.fetch(:default, nil)
|
@@ -26,15 +28,26 @@ module Servactory
|
|
26
28
|
|
27
29
|
def options_for_checks
|
28
30
|
{
|
29
|
-
types
|
30
|
-
inclusion
|
31
|
-
must
|
32
|
-
required
|
33
|
-
# internal
|
34
|
-
default:
|
31
|
+
types: types,
|
32
|
+
inclusion: inclusion,
|
33
|
+
must: must,
|
34
|
+
required: required,
|
35
|
+
# internal: internal,
|
36
|
+
default: default
|
35
37
|
}
|
36
38
|
end
|
37
39
|
|
40
|
+
def prepare_advanced_for(value)
|
41
|
+
if value.is_a?(Hash)
|
42
|
+
ARRAY_DEFAULT_VALUE.call(
|
43
|
+
is: value.fetch(:is, false),
|
44
|
+
message: value.fetch(:message, nil)
|
45
|
+
)
|
46
|
+
else
|
47
|
+
ARRAY_DEFAULT_VALUE.call(is: value)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
38
51
|
def conflict_code
|
39
52
|
return :required_vs_default if required? && default_value_present?
|
40
53
|
return :array_vs_array if array? && types.include?(Array)
|
@@ -52,7 +65,7 @@ module Servactory
|
|
52
65
|
end
|
53
66
|
|
54
67
|
def array?
|
55
|
-
Servactory::Utils.boolean?(array)
|
68
|
+
Servactory::Utils.boolean?(array[:is])
|
56
69
|
end
|
57
70
|
|
58
71
|
def required?
|
@@ -28,13 +28,18 @@ module Servactory
|
|
28
28
|
|
29
29
|
def process_input(input)
|
30
30
|
input.options_for_checks.each do |check_key, check_options|
|
31
|
-
process_option(check_key, check_options, input:)
|
31
|
+
process_option(check_key, check_options, input: input)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
def process_option(check_key, check_options, input:)
|
36
36
|
check_classes.each do |check_class|
|
37
|
-
errors_from_checks = process_check_class(
|
37
|
+
errors_from_checks = process_check_class(
|
38
|
+
check_class,
|
39
|
+
input: input,
|
40
|
+
check_key: check_key,
|
41
|
+
check_options: check_options
|
42
|
+
)
|
38
43
|
|
39
44
|
@errors.push(*errors_from_checks)
|
40
45
|
end
|
@@ -43,10 +48,10 @@ module Servactory
|
|
43
48
|
def process_check_class(check_class, input:, check_key:, check_options:)
|
44
49
|
check_class.check(
|
45
50
|
context: @context,
|
46
|
-
input
|
51
|
+
input: input,
|
47
52
|
value: @incoming_arguments.fetch(input.name, nil),
|
48
|
-
check_key
|
49
|
-
check_options:
|
53
|
+
check_key: check_key,
|
54
|
+
check_options: check_options
|
50
55
|
)
|
51
56
|
end
|
52
57
|
|
@@ -43,7 +43,7 @@ module Servactory
|
|
43
43
|
|
44
44
|
@context.assign_inputs(Servactory::Inputs.new(**@inputs_variables))
|
45
45
|
|
46
|
-
@context.class.class_eval(context_internal_variables_template)
|
46
|
+
@context.class.class_eval(context_internal_variables_template) if context_internal_variables_template.present?
|
47
47
|
|
48
48
|
@internal_variables.each do |input_name, input_value|
|
49
49
|
@context.instance_variable_set(:"@#{input_name}", input_value)
|
@@ -79,8 +79,12 @@ module Servactory
|
|
79
79
|
# private attr_reader(*[:attr_1]);
|
80
80
|
#
|
81
81
|
def context_internal_variables_template
|
82
|
-
|
83
|
-
|
82
|
+
return if @internal_variables.blank?
|
83
|
+
|
84
|
+
@context_internal_variables_template ||= <<-RUBY.squish
|
85
|
+
private;
|
86
|
+
|
87
|
+
attr_reader(*#{@internal_variables.keys});
|
84
88
|
RUBY
|
85
89
|
end
|
86
90
|
end
|
@@ -42,14 +42,16 @@ module Servactory
|
|
42
42
|
define_method(:#{internal_argument.name}=) do |value|;
|
43
43
|
Servactory::InternalArguments::Checks::Type.check!(
|
44
44
|
context: self,
|
45
|
-
internal_argument
|
46
|
-
value:
|
45
|
+
internal_argument: internal_argument,
|
46
|
+
value: value
|
47
47
|
);
|
48
48
|
|
49
49
|
instance_variable_set(:@#{internal_argument.name}, value);
|
50
50
|
end;
|
51
51
|
|
52
|
-
private
|
52
|
+
private;
|
53
|
+
|
54
|
+
attr_reader :#{internal_argument.name};
|
53
55
|
RUBY
|
54
56
|
end
|
55
57
|
end
|
@@ -35,21 +35,25 @@ module Servactory
|
|
35
35
|
# instance_variable_set(:@user, value);
|
36
36
|
# end;
|
37
37
|
#
|
38
|
-
# private
|
38
|
+
# private;
|
39
|
+
#
|
40
|
+
# attr_reader :user;
|
39
41
|
#
|
40
42
|
def context_output_argument_template_for(output_argument)
|
41
43
|
<<-RUBY.squish
|
42
44
|
define_method(:#{output_argument.name}=) do |value|;
|
43
45
|
Servactory::OutputArguments::Checks::Type.check!(
|
44
46
|
context: self,
|
45
|
-
output_argument
|
46
|
-
value:
|
47
|
+
output_argument: output_argument,
|
48
|
+
value: value
|
47
49
|
);
|
48
50
|
|
49
51
|
instance_variable_set(:@#{output_argument.name}, value);
|
50
52
|
end;
|
51
53
|
|
52
|
-
private
|
54
|
+
private;
|
55
|
+
|
56
|
+
attr_reader :#{output_argument.name};
|
53
57
|
RUBY
|
54
58
|
end
|
55
59
|
end
|
data/lib/servactory/stage/dsl.rb
CHANGED
@@ -12,10 +12,10 @@ module Servactory
|
|
12
12
|
|
13
13
|
attr_reader :stage_handyman
|
14
14
|
|
15
|
-
def stage(&)
|
15
|
+
def stage(&block)
|
16
16
|
@stage_factory ||= Factory.new
|
17
17
|
|
18
|
-
@stage_factory.instance_eval(&)
|
18
|
+
@stage_factory.instance_eval(&block)
|
19
19
|
|
20
20
|
@stage_handyman = Handyman.work_in(@stage_factory)
|
21
21
|
|
data/lib/servactory/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: servactory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
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-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: zeitwerk
|
@@ -223,7 +223,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
223
223
|
requirements:
|
224
224
|
- - ">="
|
225
225
|
- !ruby/object:Gem::Version
|
226
|
-
version:
|
226
|
+
version: 2.7.0
|
227
227
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
228
228
|
requirements:
|
229
229
|
- - ">="
|