servactory 1.9.6 → 2.0.0.rc2

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 (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 +15 -11
  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 = 6
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.6
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-10-10 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
@@ -224,17 +224,12 @@ files:
224
224
  - lib/servactory/info/dsl.rb
225
225
  - lib/servactory/info/result.rb
226
226
  - lib/servactory/inputs/collection.rb
227
- - lib/servactory/inputs/define_input_conflict.rb
228
- - lib/servactory/inputs/define_input_method.rb
229
227
  - lib/servactory/inputs/dsl.rb
230
228
  - lib/servactory/inputs/input.rb
231
- - lib/servactory/inputs/option.rb
232
- - lib/servactory/inputs/option_helper.rb
233
- - lib/servactory/inputs/option_helpers_collection.rb
234
- - lib/servactory/inputs/options_collection.rb
235
229
  - lib/servactory/inputs/tools/check_errors.rb
236
- - lib/servactory/inputs/tools/find_unnecessary.rb
230
+ - lib/servactory/inputs/tools/distributor.rb
237
231
  - lib/servactory/inputs/tools/rules.rb
232
+ - lib/servactory/inputs/tools/unnecessary.rb
238
233
  - lib/servactory/inputs/tools/validation.rb
239
234
  - lib/servactory/inputs/validations/base.rb
240
235
  - lib/servactory/inputs/validations/errors.rb
@@ -248,6 +243,15 @@ files:
248
243
  - lib/servactory/internals/internal.rb
249
244
  - lib/servactory/internals/validations/base.rb
250
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
251
255
  - lib/servactory/methods/aliases_for_make/collection.rb
252
256
  - lib/servactory/methods/dsl.rb
253
257
  - lib/servactory/methods/method.rb
@@ -288,9 +292,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
288
292
  version: 2.7.0
289
293
  required_rubygems_version: !ruby/object:Gem::Requirement
290
294
  requirements:
291
- - - ">="
295
+ - - ">"
292
296
  - !ruby/object:Gem::Version
293
- version: '0'
297
+ version: 1.3.1
294
298
  requirements: []
295
299
  rubygems_version: 3.4.17
296
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