servactory 1.3.0 → 1.4.1
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 -4
- data/lib/servactory/context/dsl.rb +10 -5
- data/lib/servactory/input_arguments/checks/inclusion.rb +2 -2
- data/lib/servactory/input_arguments/checks/must.rb +3 -1
- data/lib/servactory/input_arguments/checks/required.rb +8 -6
- data/lib/servactory/input_arguments/dsl.rb +9 -1
- data/lib/servactory/input_arguments/input_argument.rb +164 -56
- data/lib/servactory/input_arguments/option.rb +78 -0
- data/lib/servactory/input_arguments/options_collection.rb +35 -0
- data/lib/servactory/input_arguments/tools/check.rb +5 -9
- data/lib/servactory/input_arguments/workbench.rb +6 -3
- data/lib/servactory/version.rb +2 -2
- metadata +12 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40fbce39ff24b8ea522a6cbd2f2b2d48a9e09034e8cc636da53827eefb254d6f
|
4
|
+
data.tar.gz: d2f56d8b47aac242932780b1969c5b47e2da961762fd7625da776ecb9966132b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ecefb0457e5933ddc441df45adb512da42f815ca1cdb23920835aa5f39ea4e73c7eeb83832bb3d128c83a94a21126e30619af325f7afe540195e2a44cdead7a
|
7
|
+
data.tar.gz: 5d3772b974c1d23da5d2b75443d2a1437a0d547a8eb48f538391d66368f449f8065793f152401925a753eac4f908a6c7e02cbdbc8a0b4b019415da3ff44e89b3
|
data/README.md
CHANGED
@@ -2,6 +2,28 @@
|
|
2
2
|
|
3
3
|
A set of tools for building reliable services of any complexity.
|
4
4
|
|
5
|
+
[](https://rubygems.org/gems/servactory)
|
6
|
+
|
7
|
+
## Contents
|
8
|
+
|
9
|
+
- [Requirements](#requirements)
|
10
|
+
- [Getting started](#getting-started)
|
11
|
+
- [Conventions](#conventions)
|
12
|
+
- [Installation](#installation)
|
13
|
+
- [Preparation](#preparation)
|
14
|
+
- [Usage](#usage)
|
15
|
+
- [Minimal example](#minimal-example)
|
16
|
+
- [Input attributes](#input-attributes)
|
17
|
+
- [Isolated usage](#isolated-usage)
|
18
|
+
- [As an internal argument](#isolated-usage)
|
19
|
+
- [Optional inputs](#optional-inputs)
|
20
|
+
- [An array of specific values](#an-array-of-specific-values)
|
21
|
+
- [Inclusion](#inclusion)
|
22
|
+
- [Must](#must)
|
23
|
+
- [Output attributes](#output-attributes)
|
24
|
+
- [Internal attributes](#internal-attributes)
|
25
|
+
- [Result](#result)
|
26
|
+
|
5
27
|
## Requirements
|
6
28
|
|
7
29
|
- Ruby >= 2.7
|
@@ -70,7 +92,7 @@ end
|
|
70
92
|
### Minimal example
|
71
93
|
|
72
94
|
```ruby
|
73
|
-
class
|
95
|
+
class MinimalService < ApplicationService::Base
|
74
96
|
stage { make :something }
|
75
97
|
|
76
98
|
private
|
@@ -85,10 +107,10 @@ end
|
|
85
107
|
|
86
108
|
#### Isolated usage
|
87
109
|
|
88
|
-
With this approach, all input attributes are available only from `inputs`.
|
110
|
+
With this approach, all input attributes are available only from `inputs`. This is default behaviour.
|
89
111
|
|
90
112
|
```ruby
|
91
|
-
class
|
113
|
+
class UsersService::Accept < ApplicationService::Base
|
92
114
|
input :user, type: User
|
93
115
|
|
94
116
|
stage { make :accept! }
|
@@ -106,7 +128,7 @@ end
|
|
106
128
|
With this approach, all input attributes are available from `inputs` as well as directly from the context.
|
107
129
|
|
108
130
|
```ruby
|
109
|
-
class
|
131
|
+
class UsersService::Accept < ApplicationService::Base
|
110
132
|
input :user, type: User, internal: true
|
111
133
|
|
112
134
|
stage { make :accept! }
|
@@ -119,6 +141,59 @@ class UserService::Accept < ApplicationService::Base
|
|
119
141
|
end
|
120
142
|
```
|
121
143
|
|
144
|
+
#### Optional inputs
|
145
|
+
|
146
|
+
By default, all inputs are required. To make an input optional, specify `false` in the `required` option.
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
class UsersService::Create < ApplicationService::Base
|
150
|
+
input :first_name, type: String, internal: true
|
151
|
+
input :middle_name, type: String, required: false
|
152
|
+
input :last_name, type: String, internal: true
|
153
|
+
|
154
|
+
# ...
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
#### An array of specific values
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
class PymentsService::Send < ApplicationService::Base
|
162
|
+
input :invoice_numbers, type: String, array: true
|
163
|
+
|
164
|
+
# ...
|
165
|
+
end
|
166
|
+
```
|
167
|
+
|
168
|
+
#### Inclusion
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
class EventService::Send < ApplicationService::Base
|
172
|
+
input :event_name, type: String, inclusion: %w[created rejected approved]
|
173
|
+
|
174
|
+
# ...
|
175
|
+
end
|
176
|
+
```
|
177
|
+
|
178
|
+
#### Must
|
179
|
+
|
180
|
+
Sometimes there are cases that require the implementation of a specific input attribute check. In such cases `must` can help.
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
class PymentsService::Send < ApplicationService::Base
|
184
|
+
input :invoice_numbers,
|
185
|
+
type: String,
|
186
|
+
array: true,
|
187
|
+
must: {
|
188
|
+
be_6_characters: {
|
189
|
+
is: ->(value:) { value.all? { |id| id.size == 6 } }
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
# ...
|
194
|
+
end
|
195
|
+
```
|
196
|
+
|
122
197
|
### Output attributes
|
123
198
|
|
124
199
|
```ruby
|
@@ -35,11 +35,16 @@ module Servactory
|
|
35
35
|
|
36
36
|
attr_reader :context_store
|
37
37
|
|
38
|
-
def assign_data_with(arguments)
|
39
|
-
input_arguments_workbench.assign(
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
def assign_data_with(arguments) # rubocop:disable Metrics/AbcSize
|
39
|
+
input_arguments_workbench.assign(
|
40
|
+
context: context_store.context,
|
41
|
+
arguments: arguments,
|
42
|
+
collection_of_input_options: collection_of_input_options
|
43
|
+
)
|
44
|
+
|
45
|
+
internal_arguments_workbench.assign(context: context_store.context)
|
46
|
+
output_arguments_workbench.assign(context: context_store.context)
|
47
|
+
stage_handyman&.assign(context: context_store.context)
|
43
48
|
end
|
44
49
|
|
45
50
|
def prepare_data
|
@@ -5,7 +5,7 @@ module Servactory
|
|
5
5
|
module Checks
|
6
6
|
class Inclusion < Base
|
7
7
|
DEFAULT_MESSAGE = lambda do |service_class_name:, input:|
|
8
|
-
"[#{service_class_name}] Wrong value in `#{input.name}`, must be one of `#{input.inclusion}`"
|
8
|
+
"[#{service_class_name}] Wrong value in `#{input.name}`, must be one of `#{input.inclusion[:in]}`"
|
9
9
|
end
|
10
10
|
|
11
11
|
private_constant :DEFAULT_MESSAGE
|
@@ -31,7 +31,7 @@ module Servactory
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def check
|
34
|
-
return if @input.inclusion.include?(@value)
|
34
|
+
return if @input.inclusion[:in].include?(@value)
|
35
35
|
|
36
36
|
add_error(
|
37
37
|
DEFAULT_MESSAGE,
|
@@ -57,10 +57,12 @@ 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
62
|
"[#{@context.class.name}] Syntax error inside `#{code}` of `#{@input.name}` input"
|
63
63
|
|
64
|
+
puts "#{message_text}: #{e}"
|
65
|
+
|
64
66
|
add_error(
|
65
67
|
message_text,
|
66
68
|
service_class_name: @context.class.name,
|
@@ -14,14 +14,14 @@ module Servactory
|
|
14
14
|
|
15
15
|
private_constant :DEFAULT_MESSAGE
|
16
16
|
|
17
|
-
def self.check(context:, input:, value:, **)
|
18
|
-
return unless should_be_checked_for?(input)
|
17
|
+
def self.check(context:, input:, value:, check_key:, **)
|
18
|
+
return unless should_be_checked_for?(input, check_key)
|
19
19
|
|
20
20
|
new(context: context, input: input, value: value).check
|
21
21
|
end
|
22
22
|
|
23
|
-
def self.should_be_checked_for?(input)
|
24
|
-
input.required?
|
23
|
+
def self.should_be_checked_for?(input, check_key)
|
24
|
+
check_key == :required && input.required?
|
25
25
|
end
|
26
26
|
|
27
27
|
##########################################################################
|
@@ -34,15 +34,17 @@ module Servactory
|
|
34
34
|
@value = value
|
35
35
|
end
|
36
36
|
|
37
|
-
def check # rubocop:disable Metrics/MethodLength
|
37
|
+
def check # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
38
38
|
if @input.array? && @value.present?
|
39
39
|
return if @value.respond_to?(:all?) && @value.all?(&:present?)
|
40
40
|
elsif @value.present?
|
41
41
|
return
|
42
42
|
end
|
43
43
|
|
44
|
+
_, message = @input.required.values_at(:is, :message)
|
45
|
+
|
44
46
|
add_error(
|
45
|
-
DEFAULT_MESSAGE,
|
47
|
+
message.presence || DEFAULT_MESSAGE,
|
46
48
|
service_class_name: @context.class.name,
|
47
49
|
input: @input,
|
48
50
|
value: @value
|
@@ -11,13 +11,21 @@ module Servactory
|
|
11
11
|
private
|
12
12
|
|
13
13
|
def input(name, **options)
|
14
|
-
collection_of_input_arguments << InputArgument.new(
|
14
|
+
collection_of_input_arguments << InputArgument.new(
|
15
|
+
name,
|
16
|
+
collection_of_options: collection_of_input_options,
|
17
|
+
**options
|
18
|
+
)
|
15
19
|
end
|
16
20
|
|
17
21
|
def collection_of_input_arguments
|
18
22
|
@collection_of_input_arguments ||= Collection.new
|
19
23
|
end
|
20
24
|
|
25
|
+
def collection_of_input_options
|
26
|
+
@collection_of_input_options ||= OptionsCollection.new
|
27
|
+
end
|
28
|
+
|
21
29
|
def input_arguments_workbench
|
22
30
|
@input_arguments_workbench ||= Workbench.work_with(collection_of_input_arguments)
|
23
31
|
end
|
@@ -2,86 +2,194 @@
|
|
2
2
|
|
3
3
|
module Servactory
|
4
4
|
module InputArguments
|
5
|
-
class InputArgument
|
5
|
+
class InputArgument # rubocop:disable Metrics/ClassLength
|
6
6
|
ARRAY_DEFAULT_VALUE = ->(is: false, message: nil) { { is: is, message: message } }
|
7
7
|
|
8
8
|
attr_reader :name,
|
9
|
-
:
|
10
|
-
|
11
|
-
|
12
|
-
:array,
|
13
|
-
:required,
|
14
|
-
:internal,
|
15
|
-
:default
|
16
|
-
|
17
|
-
def initialize(name, type:, **options)
|
9
|
+
:collection_of_options
|
10
|
+
|
11
|
+
def initialize(name, collection_of_options:, type:, **options)
|
18
12
|
@name = name
|
19
|
-
@
|
20
|
-
|
21
|
-
@inclusion = options.fetch(:inclusion, nil)
|
22
|
-
@must = options.fetch(:must, nil)
|
23
|
-
@array = prepare_advanced_for(options.fetch(:array, ARRAY_DEFAULT_VALUE.call))
|
24
|
-
@required = options.fetch(:required, true)
|
25
|
-
@internal = options.fetch(:internal, false)
|
26
|
-
@default = options.fetch(:default, nil)
|
27
|
-
end
|
13
|
+
@collection_of_options = collection_of_options
|
28
14
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
must: must,
|
34
|
-
required: required,
|
35
|
-
# internal: internal,
|
36
|
-
default: default
|
37
|
-
}
|
38
|
-
end
|
15
|
+
add_basic_options_with(type: type, options: options)
|
16
|
+
|
17
|
+
@collection_of_options.each do |option|
|
18
|
+
self.class.attr_reader(:"#{option.name}")
|
39
19
|
|
40
|
-
|
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)
|
20
|
+
instance_variable_set(:"@#{option.name}", option.value)
|
48
21
|
end
|
49
22
|
end
|
50
23
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
return :array_vs_inclusion if array? && inclusion_present?
|
24
|
+
def add_basic_options_with(type:, options:)
|
25
|
+
# Check Class: Servactory::InputArguments::Checks::Required
|
26
|
+
add_required_option_with(options)
|
55
27
|
|
56
|
-
|
28
|
+
# Check Class: Servactory::InputArguments::Checks::Type
|
29
|
+
add_types_option_with(type)
|
30
|
+
add_default_option_with(options)
|
31
|
+
add_array_option_with(options)
|
32
|
+
|
33
|
+
# Check Class: Servactory::InputArguments::Checks::Inclusion
|
34
|
+
add_inclusion_option_with(options)
|
35
|
+
|
36
|
+
# Check Class: Servactory::InputArguments::Checks::Must
|
37
|
+
add_must_option_with(options)
|
38
|
+
|
39
|
+
# Check Class: nil
|
40
|
+
add_internal_option_with(options)
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_required_option_with(options) # rubocop:disable Metrics/MethodLength
|
44
|
+
collection_of_options << Option.new(
|
45
|
+
name: :required,
|
46
|
+
input: self,
|
47
|
+
check_class: Servactory::InputArguments::Checks::Required,
|
48
|
+
define_input_methods: lambda do
|
49
|
+
<<-RUBY
|
50
|
+
def required?
|
51
|
+
Servactory::Utils.boolean?(required[:is])
|
52
|
+
end
|
53
|
+
|
54
|
+
def optional?
|
55
|
+
!required?
|
56
|
+
end
|
57
|
+
RUBY
|
58
|
+
end,
|
59
|
+
define_conflicts: lambda do
|
60
|
+
<<-RUBY
|
61
|
+
return :required_vs_default if required? && default_value_present?
|
62
|
+
RUBY
|
63
|
+
end,
|
64
|
+
need_for_checks: true,
|
65
|
+
value_key: :is,
|
66
|
+
value_fallback: true,
|
67
|
+
**options
|
68
|
+
)
|
57
69
|
end
|
58
70
|
|
59
|
-
def
|
60
|
-
|
71
|
+
def add_types_option_with(type)
|
72
|
+
collection_of_options << Option.new(
|
73
|
+
name: :types,
|
74
|
+
input: self,
|
75
|
+
original_value: Array(type),
|
76
|
+
check_class: Servactory::InputArguments::Checks::Type,
|
77
|
+
need_for_checks: true,
|
78
|
+
value_fallback: nil,
|
79
|
+
with_advanced_mode: false
|
80
|
+
)
|
61
81
|
end
|
62
82
|
|
63
|
-
def
|
64
|
-
|
83
|
+
def add_default_option_with(options) # rubocop:disable Metrics/MethodLength
|
84
|
+
collection_of_options << Option.new(
|
85
|
+
name: :default,
|
86
|
+
input: self,
|
87
|
+
check_class: Servactory::InputArguments::Checks::Type,
|
88
|
+
define_input_methods: lambda do
|
89
|
+
<<-RUBY
|
90
|
+
def default_value_present?
|
91
|
+
!default.nil?
|
92
|
+
end
|
93
|
+
RUBY
|
94
|
+
end,
|
95
|
+
need_for_checks: true,
|
96
|
+
value_fallback: nil,
|
97
|
+
with_advanced_mode: false,
|
98
|
+
**options
|
99
|
+
)
|
65
100
|
end
|
66
101
|
|
67
|
-
def
|
68
|
-
|
102
|
+
def add_array_option_with(options) # rubocop:disable Metrics/MethodLength
|
103
|
+
collection_of_options << Option.new(
|
104
|
+
name: :array,
|
105
|
+
input: self,
|
106
|
+
check_class: Servactory::InputArguments::Checks::Type,
|
107
|
+
define_input_methods: lambda do
|
108
|
+
<<-RUBY
|
109
|
+
def array?
|
110
|
+
Servactory::Utils.boolean?(array[:is])
|
111
|
+
end
|
112
|
+
RUBY
|
113
|
+
end,
|
114
|
+
define_conflicts: lambda do
|
115
|
+
<<-RUBY
|
116
|
+
return :array_vs_array if array? && types.include?(Array)
|
117
|
+
return :array_vs_inclusion if array? && inclusion_present?
|
118
|
+
RUBY
|
119
|
+
end,
|
120
|
+
need_for_checks: false,
|
121
|
+
value_key: :is,
|
122
|
+
value_fallback: false,
|
123
|
+
**options
|
124
|
+
)
|
69
125
|
end
|
70
126
|
|
71
|
-
def
|
72
|
-
|
127
|
+
def add_inclusion_option_with(options) # rubocop:disable Metrics/MethodLength
|
128
|
+
collection_of_options << Option.new(
|
129
|
+
name: :inclusion,
|
130
|
+
input: self,
|
131
|
+
check_class: Servactory::InputArguments::Checks::Inclusion,
|
132
|
+
define_input_methods: lambda do
|
133
|
+
<<-RUBY
|
134
|
+
def inclusion_present?
|
135
|
+
inclusion[:in].is_a?(Array) && inclusion[:in].present?
|
136
|
+
end
|
137
|
+
RUBY
|
138
|
+
end,
|
139
|
+
need_for_checks: true,
|
140
|
+
value_key: :in,
|
141
|
+
value_fallback: nil,
|
142
|
+
**options
|
143
|
+
)
|
73
144
|
end
|
74
145
|
|
75
|
-
def
|
76
|
-
|
146
|
+
def add_must_option_with(options) # rubocop:disable Metrics/MethodLength
|
147
|
+
collection_of_options << Option.new(
|
148
|
+
name: :must,
|
149
|
+
input: self,
|
150
|
+
check_class: Servactory::InputArguments::Checks::Must,
|
151
|
+
define_input_methods: lambda do
|
152
|
+
<<-RUBY
|
153
|
+
def must_present?
|
154
|
+
must.present?
|
155
|
+
end
|
156
|
+
RUBY
|
157
|
+
end,
|
158
|
+
need_for_checks: true,
|
159
|
+
value_key: :is,
|
160
|
+
value_fallback: nil,
|
161
|
+
with_advanced_mode: false,
|
162
|
+
**options
|
163
|
+
)
|
77
164
|
end
|
78
165
|
|
79
|
-
def
|
80
|
-
|
166
|
+
def add_internal_option_with(options) # rubocop:disable Metrics/MethodLength
|
167
|
+
collection_of_options << Option.new(
|
168
|
+
name: :internal,
|
169
|
+
input: self,
|
170
|
+
define_input_methods: lambda do
|
171
|
+
<<-RUBY
|
172
|
+
def internal?
|
173
|
+
Servactory::Utils.boolean?(internal[:is])
|
174
|
+
end
|
175
|
+
RUBY
|
176
|
+
end,
|
177
|
+
need_for_checks: false,
|
178
|
+
check_class: nil,
|
179
|
+
value_key: :is,
|
180
|
+
value_fallback: false,
|
181
|
+
**options
|
182
|
+
)
|
81
183
|
end
|
82
184
|
|
83
|
-
def
|
84
|
-
|
185
|
+
def options_for_checks
|
186
|
+
collection_of_options.options_for_checks
|
187
|
+
end
|
188
|
+
|
189
|
+
def conflict_code
|
190
|
+
instance_eval(collection_of_options.defined_conflicts)
|
191
|
+
|
192
|
+
nil
|
85
193
|
end
|
86
194
|
|
87
195
|
def with_conflicts?
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InputArguments
|
5
|
+
class Option
|
6
|
+
DEFAULT_VALUE = ->(key:, value:, message: nil) { { key => value, message: message } }
|
7
|
+
|
8
|
+
private_constant :DEFAULT_VALUE
|
9
|
+
|
10
|
+
attr_reader :name,
|
11
|
+
:check_class,
|
12
|
+
:define_conflicts,
|
13
|
+
:need_for_checks,
|
14
|
+
:value_key,
|
15
|
+
:value
|
16
|
+
|
17
|
+
# rubocop:disable Metrics/MethodLength
|
18
|
+
def initialize(
|
19
|
+
name:,
|
20
|
+
input:,
|
21
|
+
check_class:,
|
22
|
+
need_for_checks:,
|
23
|
+
value_fallback:,
|
24
|
+
original_value: nil,
|
25
|
+
value_key: nil,
|
26
|
+
define_input_methods: nil,
|
27
|
+
define_conflicts: nil,
|
28
|
+
with_advanced_mode: true,
|
29
|
+
**options
|
30
|
+
) # do
|
31
|
+
@name = name.to_sym
|
32
|
+
@check_class = check_class
|
33
|
+
@define_conflicts = define_conflicts
|
34
|
+
@need_for_checks = need_for_checks
|
35
|
+
@value_key = value_key
|
36
|
+
|
37
|
+
@value = prepare_value_for(
|
38
|
+
original_value: original_value,
|
39
|
+
options: options,
|
40
|
+
value_fallback: value_fallback,
|
41
|
+
with_advanced_mode: with_advanced_mode
|
42
|
+
)
|
43
|
+
|
44
|
+
input.instance_eval(define_input_methods.call) if define_input_methods.present?
|
45
|
+
end
|
46
|
+
# rubocop:enable Metrics/MethodLength
|
47
|
+
|
48
|
+
def need_for_checks?
|
49
|
+
need_for_checks
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def prepare_value_for(original_value:, options:, value_fallback:, with_advanced_mode:)
|
55
|
+
return original_value if original_value.present?
|
56
|
+
|
57
|
+
return options.fetch(@name, value_fallback) unless with_advanced_mode
|
58
|
+
|
59
|
+
prepare_advanced_for(
|
60
|
+
value: options.fetch(@name, DEFAULT_VALUE.call(key: value_key, value: value_fallback)),
|
61
|
+
value_fallback: value_fallback
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
def prepare_advanced_for(value:, value_fallback:)
|
66
|
+
if value.is_a?(Hash)
|
67
|
+
DEFAULT_VALUE.call(
|
68
|
+
key: value_key,
|
69
|
+
value: value.fetch(value_key, value_fallback),
|
70
|
+
message: value.fetch(:message, nil)
|
71
|
+
)
|
72
|
+
else
|
73
|
+
DEFAULT_VALUE.call(key: value_key, value: value)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Servactory
|
4
|
+
module InputArguments
|
5
|
+
class OptionsCollection
|
6
|
+
# NOTE: http://words.steveklabnik.com/beware-subclassing-ruby-core-classes
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators :@collection, :<<, :each, :select, :map
|
9
|
+
|
10
|
+
def initialize(*)
|
11
|
+
@collection = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def check_classes
|
15
|
+
select { |option| option.check_class.present? }.map(&:check_class).uniq
|
16
|
+
end
|
17
|
+
|
18
|
+
def options_for_checks
|
19
|
+
select(&:need_for_checks?).to_h do |option|
|
20
|
+
value = if option.value.is_a?(Hash)
|
21
|
+
option.value.key?(:is) ? option.value.fetch(:is) : option.value
|
22
|
+
else
|
23
|
+
option.value
|
24
|
+
end
|
25
|
+
|
26
|
+
[option.name, value]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def defined_conflicts
|
31
|
+
map { |option| option.define_conflicts&.call }.reject(&:blank?).uniq.join
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -8,10 +8,11 @@ module Servactory
|
|
8
8
|
new(...).check!
|
9
9
|
end
|
10
10
|
|
11
|
-
def initialize(context, incoming_arguments, collection_of_input_arguments)
|
11
|
+
def initialize(context, incoming_arguments, collection_of_input_arguments, collection_of_input_options)
|
12
12
|
@context = context
|
13
13
|
@incoming_arguments = incoming_arguments
|
14
14
|
@collection_of_input_arguments = collection_of_input_arguments
|
15
|
+
@collection_of_input_options = collection_of_input_options
|
15
16
|
|
16
17
|
@errors = []
|
17
18
|
end
|
@@ -58,20 +59,15 @@ module Servactory
|
|
58
59
|
########################################################################
|
59
60
|
|
60
61
|
def check_classes
|
61
|
-
|
62
|
-
Servactory::InputArguments::Checks::Required,
|
63
|
-
Servactory::InputArguments::Checks::Type,
|
64
|
-
Servactory::InputArguments::Checks::Inclusion,
|
65
|
-
Servactory::InputArguments::Checks::Must
|
66
|
-
]
|
62
|
+
@collection_of_input_options.check_classes
|
67
63
|
end
|
68
64
|
|
69
65
|
########################################################################
|
70
66
|
|
71
67
|
def raise_errors
|
72
|
-
return if @errors.empty?
|
68
|
+
return if (tmp_errors = @errors.reject(&:blank?).uniq).empty?
|
73
69
|
|
74
|
-
raise Servactory.configuration.input_argument_error_class,
|
70
|
+
raise Servactory.configuration.input_argument_error_class, tmp_errors.first
|
75
71
|
end
|
76
72
|
end
|
77
73
|
end
|
@@ -11,9 +11,10 @@ module Servactory
|
|
11
11
|
@collection_of_input_arguments = collection_of_input_arguments
|
12
12
|
end
|
13
13
|
|
14
|
-
def assign(context:, arguments:)
|
14
|
+
def assign(context:, arguments:, collection_of_input_options:)
|
15
15
|
@context = context
|
16
16
|
@incoming_arguments = arguments
|
17
|
+
@collection_of_input_options = collection_of_input_options
|
17
18
|
end
|
18
19
|
|
19
20
|
def find_unnecessary!
|
@@ -29,12 +30,14 @@ module Servactory
|
|
29
30
|
end
|
30
31
|
|
31
32
|
def check!
|
32
|
-
Tools::Check.check!(context, @incoming_arguments, collection_of_input_arguments)
|
33
|
+
Tools::Check.check!(context, @incoming_arguments, collection_of_input_arguments, collection_of_input_options)
|
33
34
|
end
|
34
35
|
|
35
36
|
private
|
36
37
|
|
37
|
-
attr_reader :context,
|
38
|
+
attr_reader :context,
|
39
|
+
:collection_of_input_arguments,
|
40
|
+
:collection_of_input_options
|
38
41
|
end
|
39
42
|
end
|
40
43
|
end
|
data/lib/servactory/version.rb
CHANGED
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: servactory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.1
|
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-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: zeitwerk
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.6'
|
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: '2.6'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activesupport
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
33
|
+
version: '7.0'
|
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: '0'
|
40
|
+
version: '7.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -178,6 +178,8 @@ files:
|
|
178
178
|
- lib/servactory/input_arguments/collection.rb
|
179
179
|
- lib/servactory/input_arguments/dsl.rb
|
180
180
|
- lib/servactory/input_arguments/input_argument.rb
|
181
|
+
- lib/servactory/input_arguments/option.rb
|
182
|
+
- lib/servactory/input_arguments/options_collection.rb
|
181
183
|
- lib/servactory/input_arguments/tools/check.rb
|
182
184
|
- lib/servactory/input_arguments/tools/find_unnecessary.rb
|
183
185
|
- lib/servactory/input_arguments/tools/prepare.rb
|