servactory 1.9.5 → 2.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/config/locales/en.yml +18 -4
  3. data/config/locales/ru.yml +20 -6
  4. data/lib/servactory/configuration/dsl.rb +2 -0
  5. data/lib/servactory/configuration/factory.rb +8 -0
  6. data/lib/servactory/configuration/setup.rb +20 -4
  7. data/lib/servactory/context/workspace/inputs.rb +41 -7
  8. data/lib/servactory/context/workspace/outputs.rb +1 -1
  9. data/lib/servactory/context/workspace.rb +0 -1
  10. data/lib/servactory/dsl.rb +17 -0
  11. data/lib/servactory/inputs/collection.rb +1 -1
  12. data/lib/servactory/inputs/dsl.rb +2 -0
  13. data/lib/servactory/inputs/input.rb +101 -82
  14. data/lib/servactory/inputs/tools/distributor.rb +24 -0
  15. data/lib/servactory/inputs/tools/rules.rb +3 -3
  16. data/lib/servactory/inputs/tools/{find_unnecessary.rb → unnecessary.rb} +4 -4
  17. data/lib/servactory/inputs/tools/validation.rb +5 -7
  18. data/lib/servactory/inputs/validations/inclusion.rb +14 -9
  19. data/lib/servactory/inputs/validations/must.rb +26 -17
  20. data/lib/servactory/inputs/validations/required.rb +15 -10
  21. data/lib/servactory/inputs/validations/type.rb +85 -34
  22. data/lib/servactory/inputs/workspace.rb +6 -3
  23. data/lib/servactory/internals/dsl.rb +6 -1
  24. data/lib/servactory/internals/internal.rb +82 -14
  25. data/lib/servactory/internals/validations/type.rb +110 -29
  26. data/lib/servactory/maintenance/attributes/define_conflict.rb +15 -0
  27. data/lib/servactory/maintenance/attributes/define_method.rb +17 -0
  28. data/lib/servactory/maintenance/attributes/option.rb +115 -0
  29. data/lib/servactory/maintenance/attributes/option_helper.rb +17 -0
  30. data/lib/servactory/maintenance/attributes/option_helpers_collection.rb +20 -0
  31. data/lib/servactory/maintenance/attributes/options_collection.rb +48 -0
  32. data/lib/servactory/maintenance/collection_mode/class_names_collection.rb +16 -0
  33. data/lib/servactory/maintenance/hash_mode/class_names_collection.rb +16 -0
  34. data/lib/servactory/maintenance/validations/object_schema.rb +119 -0
  35. data/lib/servactory/methods/workspace.rb +2 -0
  36. data/lib/servactory/outputs/dsl.rb +6 -1
  37. data/lib/servactory/outputs/output.rb +80 -19
  38. data/lib/servactory/outputs/validations/type.rb +110 -31
  39. data/lib/servactory/version.rb +5 -4
  40. metadata +33 -15
  41. data/lib/servactory/inputs/define_input_conflict.rb +0 -13
  42. data/lib/servactory/inputs/define_input_method.rb +0 -15
  43. data/lib/servactory/inputs/option.rb +0 -98
  44. data/lib/servactory/inputs/option_helper.rb +0 -15
  45. data/lib/servactory/inputs/option_helpers_collection.rb +0 -18
  46. data/lib/servactory/inputs/options_collection.rb +0 -46
@@ -4,36 +4,97 @@ module Servactory
4
4
  module Outputs
5
5
  class Output
6
6
  attr_reader :name,
7
- :types,
8
- :required,
9
- :default
7
+ :collection_mode_class_names,
8
+ :hash_mode_class_names
10
9
 
11
- def initialize(name, type:, **options)
10
+ def initialize(
11
+ name,
12
+ type:,
13
+ collection_mode_class_names:,
14
+ hash_mode_class_names:,
15
+ **options
16
+ )
12
17
  @name = name
13
- @types = Array(type)
18
+ @collection_mode_class_names = collection_mode_class_names
19
+ @hash_mode_class_names = hash_mode_class_names
14
20
 
15
- @required = options.fetch(:required, true)
16
- @default = required? ? nil : options.fetch(:default, nil)
21
+ add_basic_options_with(type: type, options: options)
17
22
  end
18
23
 
19
- def options_for_checks
20
- {
21
- types: types,
22
- required: required,
23
- default: default
24
- }
24
+ def method_missing(name, *args, &block)
25
+ option = collection_of_options.find_by(name: name)
26
+
27
+ return super if option.nil?
28
+
29
+ option.body
30
+ end
31
+
32
+ def respond_to_missing?(name, *)
33
+ collection_of_options.names.include?(name) || super
34
+ end
35
+
36
+ def add_basic_options_with(type:, options:)
37
+ # Check Class: Servactory::Outputs::Validations::Type
38
+ add_types_option_with(type)
39
+ add_collection_option_with(type, options)
40
+ add_object_option_with(type, options)
41
+ end
42
+
43
+ def add_types_option_with(type)
44
+ collection_of_options << Servactory::Maintenance::Attributes::Option.new(
45
+ name: :types,
46
+ attribute: self,
47
+ validation_class: Servactory::Internals::Validations::Type,
48
+ original_value: Array(type),
49
+ need_for_checks: true,
50
+ body_fallback: nil,
51
+ with_advanced_mode: false
52
+ )
25
53
  end
26
54
 
27
- def required?
28
- Servactory::Utils.true?(required)
55
+ def add_collection_option_with(type, options) # rubocop:disable Metrics/MethodLength
56
+ collection_of_options << Servactory::Maintenance::Attributes::Option.new(
57
+ name: :consists_of,
58
+ attribute: self,
59
+ validation_class: Servactory::Internals::Validations::Type,
60
+ define_methods: [
61
+ Servactory::Maintenance::Attributes::DefineMethod.new(
62
+ name: :collection_mode?,
63
+ content: ->(**) { collection_mode_class_names.include?(type) }
64
+ )
65
+ ],
66
+ need_for_checks: false,
67
+ body_key: :type,
68
+ body_value: String,
69
+ body_fallback: String,
70
+ **options
71
+ )
29
72
  end
30
73
 
31
- def optional?
32
- !required?
74
+ def add_object_option_with(type, options) # rubocop:disable Metrics/MethodLength
75
+ collection_of_options << Servactory::Maintenance::Attributes::Option.new(
76
+ name: :schema,
77
+ attribute: self,
78
+ validation_class: Servactory::Inputs::Validations::Type,
79
+ define_methods: [
80
+ Servactory::Maintenance::Attributes::DefineMethod.new(
81
+ name: :hash_mode?,
82
+ content: ->(**) { hash_mode_class_names.include?(type) }
83
+ )
84
+ ],
85
+ need_for_checks: false,
86
+ body_fallback: {},
87
+ with_advanced_mode: false,
88
+ **options
89
+ )
33
90
  end
34
91
 
35
- def default_value_present?
36
- !default.nil?
92
+ def collection_of_options
93
+ @collection_of_options ||= Servactory::Maintenance::Attributes::OptionsCollection.new
94
+ end
95
+
96
+ def options_for_checks
97
+ collection_of_options.options_for_checks
37
98
  end
38
99
  end
39
100
  end
@@ -4,22 +4,63 @@ module Servactory
4
4
  module Outputs
5
5
  module Validations
6
6
  class Type < Base
7
- DEFAULT_MESSAGE = lambda do |service_class_name:, output:, expected_type:, given_type:|
8
- I18n.t(
9
- "servactory.outputs.checks.type.default_error",
10
- service_class_name: service_class_name,
11
- output_name: output.name,
12
- expected_type: expected_type,
13
- given_type: given_type
14
- )
7
+ DEFAULT_MESSAGE = lambda do |service_class_name:, output:, value:, key_name:, expected_type:, given_type:| # rubocop:disable Metrics/BlockLength
8
+ if output.collection_mode?
9
+ collection_message = output.consists_of.fetch(:message)
10
+
11
+ if collection_message.is_a?(Proc)
12
+ collection_message.call(output: output, expected_type: expected_type)
13
+ elsif collection_message.is_a?(String) && collection_message.present?
14
+ collection_message
15
+ elsif value.is_a?(output.types.fetch(0, Array))
16
+ I18n.t(
17
+ "servactory.outputs.checks.type.default_error.for_collection.wrong_element_type",
18
+ service_class_name: service_class_name,
19
+ output_name: output.name,
20
+ expected_type: expected_type,
21
+ given_type: given_type
22
+ )
23
+ else
24
+ I18n.t(
25
+ "servactory.outputs.checks.type.default_error.for_collection.wrong_type",
26
+ service_class_name: service_class_name,
27
+ output_name: output.name,
28
+ expected_type: output.types.fetch(0, Array),
29
+ given_type: value.class.name
30
+ )
31
+ end
32
+ elsif output.hash_mode? && key_name.present?
33
+ I18n.t(
34
+ "servactory.outputs.checks.type.default_error.for_hash.wrong_element_type",
35
+ service_class_name: service_class_name,
36
+ output_name: output.name,
37
+ key_name: key_name,
38
+ expected_type: expected_type,
39
+ given_type: given_type
40
+ )
41
+ else
42
+ I18n.t(
43
+ "servactory.outputs.checks.type.default_error.default",
44
+ service_class_name: service_class_name,
45
+ output_name: output.name,
46
+ expected_type: expected_type,
47
+ given_type: given_type
48
+ )
49
+ end
15
50
  end
16
51
 
17
52
  private_constant :DEFAULT_MESSAGE
18
53
 
19
54
  def self.validate!(...)
55
+ return unless should_be_checked?
56
+
20
57
  new(...).validate!
21
58
  end
22
59
 
60
+ def self.should_be_checked?
61
+ true
62
+ end
63
+
23
64
  ##########################################################################
24
65
 
25
66
  def initialize(context:, output:, value:)
@@ -30,40 +71,78 @@ module Servactory
30
71
  @value = value
31
72
  end
32
73
 
33
- def validate!
34
- return unless should_be_checked?
74
+ def validate! # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
75
+ object_schema_validator = nil
76
+
77
+ return if prepared_types.any? do |type|
78
+ if @output.collection_mode?
79
+ @value.is_a?(@output.types.fetch(0, Array)) &&
80
+ @value.respond_to?(:all?) && @value.all?(type)
81
+ elsif @output.hash_mode?
82
+ object_schema_validator = Servactory::Maintenance::Validations::ObjectSchema.validate(
83
+ object: @value,
84
+ schema: @output.schema
85
+ )
86
+
87
+ object_schema_validator.valid?
88
+ else
89
+ @value.is_a?(type)
90
+ end
91
+ end
92
+
93
+ if (first_error = object_schema_validator&.errors&.first).present?
94
+ raise_default_object_error_with(first_error)
95
+ end
96
+
97
+ raise_default_error
98
+ end
99
+
100
+ private
35
101
 
36
- return if prepared_types.any? { |type| @value.is_a?(type) }
102
+ def prepared_types
103
+ @prepared_types ||=
104
+ if @output.collection_mode?
105
+ prepared_types_from(Array(@output.consists_of.fetch(:type, [])))
106
+ else
107
+ prepared_types_from(@output.types)
108
+ end
109
+ end
37
110
 
111
+ def prepared_types_from(types)
112
+ types.map do |type|
113
+ if type.is_a?(String)
114
+ Object.const_get(type)
115
+ else
116
+ type
117
+ end
118
+ end
119
+ end
120
+
121
+ ########################################################################
122
+
123
+ def raise_default_object_error_with(error)
38
124
  raise_error_with(
39
125
  DEFAULT_MESSAGE,
40
126
  service_class_name: @context.class.name,
41
127
  output: @output,
42
- expected_type: prepared_types.join(", "),
43
- given_type: @value.class.name
128
+ value: @value,
129
+ key_name: error.fetch(:name),
130
+ expected_type: error.fetch(:expected_type),
131
+ given_type: error.fetch(:given_type)
44
132
  )
45
133
  end
46
134
 
47
- private
48
-
49
- def should_be_checked?
50
- @output.required? || (
51
- @output.optional? && !@output.default.nil?
52
- ) || (
53
- @output.optional? && !@value.nil?
135
+ def raise_default_error
136
+ raise_error_with(
137
+ DEFAULT_MESSAGE,
138
+ service_class_name: @context.class.name,
139
+ output: @output,
140
+ value: @value,
141
+ key_name: nil,
142
+ expected_type: prepared_types.join(", "),
143
+ given_type: @value.class.name
54
144
  )
55
145
  end
56
-
57
- def prepared_types
58
- @prepared_types ||=
59
- Array(@output.types).map do |type|
60
- if type.is_a?(String)
61
- Object.const_get(type)
62
- else
63
- type
64
- end
65
- end
66
- end
67
146
  end
68
147
  end
69
148
  end
@@ -2,10 +2,11 @@
2
2
 
3
3
  module Servactory
4
4
  module VERSION
5
- MAJOR = 1
6
- MINOR = 9
7
- PATCH = 5
5
+ MAJOR = 2
6
+ MINOR = 0
7
+ PATCH = 0
8
+ PRE = "rc2"
8
9
 
9
- STRING = [MAJOR, MINOR, PATCH].join(".")
10
+ STRING = [MAJOR, MINOR, PATCH, PRE].compact.join(".")
10
11
  end
11
12
  end
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.9.5
4
+ version: 2.0.0.rc2
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-08-19 00:00:00.000000000 Z
11
+ date: 2023-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '7.0'
19
+ version: 7.0.8
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: '7.0'
26
+ version: 7.0.8
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: i18n
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '13.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rbs
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 3.1.3
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 3.1.3
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rspec
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -156,14 +170,14 @@ dependencies:
156
170
  requirements:
157
171
  - - "~>"
158
172
  - !ruby/object:Gem::Version
159
- version: '1.4'
173
+ version: '1.5'
160
174
  type: :development
161
175
  prerelease: false
162
176
  version_requirements: !ruby/object:Gem::Requirement
163
177
  requirements:
164
178
  - - "~>"
165
179
  - !ruby/object:Gem::Version
166
- version: '1.4'
180
+ version: '1.5'
167
181
  - !ruby/object:Gem::Dependency
168
182
  name: yard
169
183
  requirement: !ruby/object:Gem::Requirement
@@ -210,17 +224,12 @@ files:
210
224
  - lib/servactory/info/dsl.rb
211
225
  - lib/servactory/info/result.rb
212
226
  - lib/servactory/inputs/collection.rb
213
- - lib/servactory/inputs/define_input_conflict.rb
214
- - lib/servactory/inputs/define_input_method.rb
215
227
  - lib/servactory/inputs/dsl.rb
216
228
  - lib/servactory/inputs/input.rb
217
- - lib/servactory/inputs/option.rb
218
- - lib/servactory/inputs/option_helper.rb
219
- - lib/servactory/inputs/option_helpers_collection.rb
220
- - lib/servactory/inputs/options_collection.rb
221
229
  - lib/servactory/inputs/tools/check_errors.rb
222
- - lib/servactory/inputs/tools/find_unnecessary.rb
230
+ - lib/servactory/inputs/tools/distributor.rb
223
231
  - lib/servactory/inputs/tools/rules.rb
232
+ - lib/servactory/inputs/tools/unnecessary.rb
224
233
  - lib/servactory/inputs/tools/validation.rb
225
234
  - lib/servactory/inputs/validations/base.rb
226
235
  - lib/servactory/inputs/validations/errors.rb
@@ -234,6 +243,15 @@ files:
234
243
  - lib/servactory/internals/internal.rb
235
244
  - lib/servactory/internals/validations/base.rb
236
245
  - lib/servactory/internals/validations/type.rb
246
+ - lib/servactory/maintenance/attributes/define_conflict.rb
247
+ - lib/servactory/maintenance/attributes/define_method.rb
248
+ - lib/servactory/maintenance/attributes/option.rb
249
+ - lib/servactory/maintenance/attributes/option_helper.rb
250
+ - lib/servactory/maintenance/attributes/option_helpers_collection.rb
251
+ - lib/servactory/maintenance/attributes/options_collection.rb
252
+ - lib/servactory/maintenance/collection_mode/class_names_collection.rb
253
+ - lib/servactory/maintenance/hash_mode/class_names_collection.rb
254
+ - lib/servactory/maintenance/validations/object_schema.rb
237
255
  - lib/servactory/methods/aliases_for_make/collection.rb
238
256
  - lib/servactory/methods/dsl.rb
239
257
  - lib/servactory/methods/method.rb
@@ -274,9 +292,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
274
292
  version: 2.7.0
275
293
  required_rubygems_version: !ruby/object:Gem::Requirement
276
294
  requirements:
277
- - - ">="
295
+ - - ">"
278
296
  - !ruby/object:Gem::Version
279
- version: '0'
297
+ version: 1.3.1
280
298
  requirements: []
281
299
  rubygems_version: 3.4.17
282
300
  signing_key:
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Servactory
4
- module Inputs
5
- class DefineInputConflict
6
- attr_reader :content
7
-
8
- def initialize(content:)
9
- @content = content
10
- end
11
- end
12
- end
13
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Servactory
4
- module Inputs
5
- class DefineInputMethod
6
- attr_reader :name,
7
- :content
8
-
9
- def initialize(name:, content:)
10
- @name = name.to_sym
11
- @content = content
12
- end
13
- end
14
- end
15
- end
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Servactory
4
- module Inputs
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
- :validation_class,
12
- :define_input_methods,
13
- :define_input_conflicts,
14
- :need_for_checks,
15
- :value_key,
16
- :value
17
-
18
- # rubocop:disable Metrics/MethodLength
19
- def initialize(
20
- name:,
21
- input:,
22
- validation_class:,
23
- need_for_checks:,
24
- value_fallback:,
25
- original_value: nil,
26
- value_key: nil,
27
- define_input_methods: nil,
28
- define_input_conflicts: nil,
29
- with_advanced_mode: true,
30
- **options
31
- ) # do
32
- @name = name.to_sym
33
- @validation_class = validation_class
34
- @define_input_methods = define_input_methods
35
- @define_input_conflicts = define_input_conflicts
36
- @need_for_checks = need_for_checks
37
- @value_key = value_key
38
-
39
- @value = prepare_value_for(
40
- original_value: original_value,
41
- options: options,
42
- value_fallback: value_fallback,
43
- with_advanced_mode: with_advanced_mode
44
- )
45
-
46
- prepare_input_methods_for(input)
47
- end
48
- # rubocop:enable Metrics/MethodLength
49
-
50
- def need_for_checks?
51
- need_for_checks
52
- end
53
-
54
- private
55
-
56
- def prepare_value_for(original_value:, options:, value_fallback:, with_advanced_mode:)
57
- return original_value if original_value.present?
58
-
59
- return options.fetch(@name, value_fallback) unless with_advanced_mode
60
-
61
- prepare_advanced_for(
62
- value: options.fetch(@name, DEFAULT_VALUE.call(key: value_key, value: value_fallback)),
63
- value_fallback: value_fallback
64
- )
65
- end
66
-
67
- def prepare_advanced_for(value:, value_fallback:)
68
- if value.is_a?(Hash)
69
- message = value.fetch(:message, nil)
70
-
71
- DEFAULT_VALUE.call(
72
- key: value_key,
73
- value: value.fetch(value_key, message.present? ? true : value_fallback),
74
- message: message
75
- )
76
- else
77
- DEFAULT_VALUE.call(key: value_key, value: value)
78
- end
79
- end
80
-
81
- def prepare_input_methods_for(input)
82
- input.instance_eval(define_input_methods_template) if define_input_methods_template.present?
83
- end
84
-
85
- def define_input_methods_template
86
- return if @define_input_methods.blank?
87
-
88
- @define_input_methods_template ||= @define_input_methods.map do |define_input_method|
89
- <<-RUBY
90
- def #{define_input_method.name}
91
- #{define_input_method.content.call(value: @value)}
92
- end
93
- RUBY
94
- end.join("\n")
95
- end
96
- end
97
- end
98
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Servactory
4
- module Inputs
5
- class OptionHelper
6
- attr_reader :name,
7
- :equivalent
8
-
9
- def initialize(name:, equivalent:)
10
- @name = name
11
- @equivalent = equivalent
12
- end
13
- end
14
- end
15
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Servactory
4
- module Inputs
5
- class OptionHelpersCollection
6
- extend Forwardable
7
- def_delegators :@collection, :<<, :find, :merge
8
-
9
- def initialize(collection)
10
- @collection = collection
11
- end
12
-
13
- def find_by(name:)
14
- find { |helper| helper.name == name }
15
- end
16
- end
17
- end
18
- end
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Servactory
4
- module Inputs
5
- class OptionsCollection
6
- extend Forwardable
7
- def_delegators :@collection, :<<, :filter, :each, :map, :flat_map, :find
8
-
9
- def initialize(*)
10
- @collection = Set.new
11
- end
12
-
13
- def names
14
- map(&:name)
15
- end
16
-
17
- def validation_classes
18
- filter { |option| option.validation_class.present? }.map(&:validation_class).uniq
19
- end
20
-
21
- def options_for_checks
22
- filter(&:need_for_checks?).to_h do |option|
23
- value = if option.value.is_a?(Hash)
24
- option.value.key?(:is) ? option.value.fetch(:is) : option.value
25
- else
26
- option.value
27
- end
28
-
29
- [option.name, value]
30
- end
31
- end
32
-
33
- def defined_conflict_code
34
- flat_map do |option|
35
- option.define_input_conflicts&.map do |define_input_conflict|
36
- define_input_conflict.content.call
37
- end
38
- end.reject(&:blank?).first
39
- end
40
-
41
- def find_by(name:)
42
- find { |option| option.name == name }
43
- end
44
- end
45
- end
46
- end