servactory 1.9.6 → 2.0.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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/config/locales/en.yml +19 -4
  3. data/config/locales/ru.yml +21 -6
  4. data/lib/servactory/{methods/method.rb → actions/action.rb} +2 -2
  5. data/lib/servactory/{methods/aliases_for_make → actions/aliases}/collection.rb +2 -2
  6. data/lib/servactory/{methods/method_collection.rb → actions/collection.rb} +3 -3
  7. data/lib/servactory/{methods → actions}/dsl.rb +9 -9
  8. data/lib/servactory/{methods/shortcuts_for_make → actions/shortcuts}/collection.rb +2 -2
  9. data/lib/servactory/actions/stages/collection.rb +20 -0
  10. data/lib/servactory/actions/stages/stage.rb +30 -0
  11. data/lib/servactory/{methods → actions}/tools/runner.rb +1 -1
  12. data/lib/servactory/{methods → actions}/workspace.rb +4 -2
  13. data/lib/servactory/base.rb +1 -1
  14. data/lib/servactory/configuration/dsl.rb +4 -2
  15. data/lib/servactory/configuration/factory.rb +12 -4
  16. data/lib/servactory/configuration/setup.rb +24 -8
  17. data/lib/servactory/context/workspace/inputs.rb +43 -7
  18. data/lib/servactory/context/workspace/outputs.rb +1 -1
  19. data/lib/servactory/context/workspace.rb +0 -4
  20. data/lib/servactory/dsl.rb +18 -1
  21. data/lib/servactory/inputs/collection.rb +1 -1
  22. data/lib/servactory/inputs/dsl.rb +2 -0
  23. data/lib/servactory/inputs/input.rb +106 -88
  24. data/lib/servactory/inputs/tools/distributor.rb +24 -0
  25. data/lib/servactory/inputs/tools/rules.rb +3 -3
  26. data/lib/servactory/inputs/tools/{find_unnecessary.rb → unnecessary.rb} +4 -4
  27. data/lib/servactory/inputs/tools/validation.rb +5 -7
  28. data/lib/servactory/inputs/validations/base.rb +1 -1
  29. data/lib/servactory/inputs/validations/inclusion.rb +15 -10
  30. data/lib/servactory/inputs/validations/must.rb +26 -17
  31. data/lib/servactory/inputs/validations/required.rb +16 -11
  32. data/lib/servactory/inputs/validations/type.rb +19 -69
  33. data/lib/servactory/inputs/workspace.rb +6 -3
  34. data/lib/servactory/internals/dsl.rb +6 -1
  35. data/lib/servactory/internals/internal.rb +81 -14
  36. data/lib/servactory/internals/validations/base.rb +1 -1
  37. data/lib/servactory/internals/validations/type.rb +6 -43
  38. data/lib/servactory/maintenance/attributes/define_conflict.rb +15 -0
  39. data/lib/servactory/maintenance/attributes/define_method.rb +17 -0
  40. data/lib/servactory/maintenance/attributes/option.rb +121 -0
  41. data/lib/servactory/maintenance/attributes/option_helper.rb +17 -0
  42. data/lib/servactory/maintenance/attributes/option_helpers_collection.rb +20 -0
  43. data/lib/servactory/maintenance/attributes/options_collection.rb +48 -0
  44. data/lib/servactory/maintenance/collection_mode/class_names_collection.rb +16 -0
  45. data/lib/servactory/maintenance/hash_mode/class_names_collection.rb +16 -0
  46. data/lib/servactory/maintenance/validations/collection.rb +66 -0
  47. data/lib/servactory/maintenance/validations/object_schema.rb +116 -0
  48. data/lib/servactory/maintenance/validations/types.rb +181 -0
  49. data/lib/servactory/outputs/dsl.rb +6 -1
  50. data/lib/servactory/outputs/output.rb +79 -19
  51. data/lib/servactory/outputs/validations/base.rb +1 -1
  52. data/lib/servactory/outputs/validations/type.rb +6 -45
  53. data/lib/servactory/version.rb +5 -4
  54. data/lib/servactory.rb +1 -1
  55. metadata +56 -30
  56. data/lib/servactory/inputs/define_input_conflict.rb +0 -13
  57. data/lib/servactory/inputs/define_input_method.rb +0 -15
  58. data/lib/servactory/inputs/option.rb +0 -98
  59. data/lib/servactory/inputs/option_helper.rb +0 -15
  60. data/lib/servactory/inputs/option_helpers_collection.rb +0 -18
  61. data/lib/servactory/inputs/options_collection.rb +0 -46
  62. data/lib/servactory/methods/stage.rb +0 -28
  63. data/lib/servactory/methods/stage_collection.rb +0 -18
@@ -4,97 +4,47 @@ module Servactory
4
4
  module Inputs
5
5
  module Validations
6
6
  class Type < Base
7
- DEFAULT_MESSAGE = lambda do |service_class_name:, input:, expected_type:, given_type:|
8
- if input.array?
9
- array_message = input.array[:message]
7
+ def self.check(context:, input:, check_key:, **)
8
+ return unless should_be_checked_for?(input, check_key)
10
9
 
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
- I18n.t(
17
- "servactory.inputs.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
- )
23
- end
24
- else
25
- I18n.t(
26
- "servactory.inputs.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
- )
32
- end
33
- end
34
-
35
- private_constant :DEFAULT_MESSAGE
36
-
37
- def self.check(context:, input:, value:, check_key:, check_options:)
38
- return unless should_be_checked_for?(input, value, check_key)
39
-
40
- new(context: context, input: input, value: value, types: check_options).check
10
+ new(context: context, input: input).check
41
11
  end
42
12
 
43
- def self.should_be_checked_for?(input, value, check_key)
13
+ def self.should_be_checked_for?(input, check_key)
44
14
  check_key == :types && (
45
15
  input.required? || (
46
16
  input.optional? && !input.default.nil?
47
17
  ) || (
48
- input.optional? && !value.nil?
18
+ input.optional? && !input.value.nil?
49
19
  )
50
20
  )
51
21
  end
52
22
 
53
- ##########################################################################
54
-
55
- def initialize(context:, input:, value:, types:)
23
+ def initialize(context:, input:)
56
24
  super()
57
25
 
58
26
  @context = context
59
27
  @input = input
60
- @value = value
61
- @types = types
62
28
  end
63
29
 
64
- def check # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
65
- return if prepared_types.any? do |type|
66
- if @input.array?
67
- prepared_value.is_a?(::Array) &&
68
- prepared_value.respond_to?(:all?) && prepared_value.all?(type)
69
- else
70
- prepared_value.is_a?(type)
71
- end
72
- end
73
-
74
- add_error(
75
- DEFAULT_MESSAGE,
76
- service_class_name: @context.class.name,
77
- input: @input,
78
- expected_type: prepared_types.join(", "),
79
- given_type: prepared_value.class.name
30
+ def check
31
+ Servactory::Maintenance::Validations::Types.validate!(
32
+ context: @context,
33
+ attribute: @input,
34
+ types: @input.types,
35
+ value: prepared_value,
36
+ error_callback: ->(**args) { add_error(**args) }
80
37
  )
81
38
  end
82
39
 
83
- ########################################################################
84
-
85
- def prepared_types
86
- @prepared_types ||=
87
- @types.map do |type|
88
- if type.is_a?(String)
89
- Object.const_get(type)
90
- else
91
- type
92
- end
93
- end
94
- end
40
+ private
95
41
 
96
42
  def prepared_value
97
- @prepared_value ||= @input.optional? && !@input.default.nil? && @value.blank? ? @input.default : @value
43
+ @prepared_value ||= if @input.optional? && !@input.default.nil? && @input.value.blank?
44
+ @input.default
45
+ else
46
+ @input.value
47
+ end
98
48
  end
99
49
  end
100
50
  end
@@ -3,12 +3,15 @@
3
3
  module Servactory
4
4
  module Inputs
5
5
  module Workspace
6
+ private
7
+
6
8
  def call!(incoming_arguments:, collection_of_inputs:, **)
7
9
  super
8
10
 
9
- Tools::FindUnnecessary.validate!(self, incoming_arguments, collection_of_inputs)
10
- Tools::Rules.validate!(self, collection_of_inputs)
11
- Servactory::Inputs::Tools::Validation.validate!(self, incoming_arguments, collection_of_inputs)
11
+ Tools::Unnecessary.find!(self, incoming_arguments, collection_of_inputs)
12
+ Tools::Distributor.assign!(incoming_arguments, collection_of_inputs)
13
+ Tools::Rules.check!(self, collection_of_inputs)
14
+ Tools::Validation.validate!(self, collection_of_inputs)
12
15
  end
13
16
  end
14
17
  end
@@ -17,7 +17,12 @@ module Servactory
17
17
  private
18
18
 
19
19
  def internal(name, **options)
20
- collection_of_internals << Internal.new(name, **options)
20
+ collection_of_internals << Internal.new(
21
+ name,
22
+ collection_mode_class_names: config.collection_mode_class_names,
23
+ hash_mode_class_names: config.hash_mode_class_names,
24
+ **options
25
+ )
21
26
  end
22
27
 
23
28
  def collection_of_internals
@@ -4,29 +4,96 @@ module Servactory
4
4
  module Internals
5
5
  class Internal
6
6
  attr_reader :name,
7
- :types,
8
- :required
7
+ :collection_mode_class_names,
8
+ :hash_mode_class_names
9
9
 
10
- def initialize(name, type:, **_options)
10
+ def initialize(
11
+ name,
12
+ collection_mode_class_names:,
13
+ hash_mode_class_names:,
14
+ **options
15
+ )
11
16
  @name = name
12
- @types = Array(type)
17
+ @collection_mode_class_names = collection_mode_class_names
18
+ @hash_mode_class_names = hash_mode_class_names
13
19
 
14
- @required = options.fetch(:required, true)
20
+ add_basic_options_with(options)
15
21
  end
16
22
 
17
- def options_for_checks
18
- {
19
- types: types,
20
- required: required
21
- }
23
+ def method_missing(name, *args, &block)
24
+ option = collection_of_options.find_by(name: name)
25
+
26
+ return super if option.nil?
27
+
28
+ option.body
29
+ end
30
+
31
+ def respond_to_missing?(name, *)
32
+ collection_of_options.names.include?(name) || super
33
+ end
34
+
35
+ def add_basic_options_with(options)
36
+ # Check Class: Servactory::Internals::Validations::Type
37
+ add_types_option_with(options)
38
+ add_collection_option_with(options)
39
+ add_hash_option_with(options)
22
40
  end
23
41
 
24
- def required?
25
- required
42
+ def add_types_option_with(options)
43
+ collection_of_options << Servactory::Maintenance::Attributes::Option.new(
44
+ name: :types,
45
+ attribute: self,
46
+ validation_class: Servactory::Internals::Validations::Type,
47
+ original_value: Array(options.fetch(:type)),
48
+ need_for_checks: true,
49
+ body_fallback: nil,
50
+ with_advanced_mode: false
51
+ )
26
52
  end
27
53
 
28
- def optional?
29
- !required
54
+ def add_collection_option_with(options) # rubocop:disable Metrics/MethodLength
55
+ collection_of_options << Servactory::Maintenance::Attributes::Option.new(
56
+ name: :consists_of,
57
+ attribute: self,
58
+ validation_class: Servactory::Internals::Validations::Type,
59
+ define_methods: [
60
+ Servactory::Maintenance::Attributes::DefineMethod.new(
61
+ name: :collection_mode?,
62
+ content: ->(**) { collection_mode_class_names.include?(options.fetch(:type)) }
63
+ )
64
+ ],
65
+ need_for_checks: false,
66
+ body_key: :type,
67
+ body_value: String,
68
+ body_fallback: String,
69
+ **options
70
+ )
71
+ end
72
+
73
+ def add_hash_option_with(options) # rubocop:disable Metrics/MethodLength
74
+ collection_of_options << Servactory::Maintenance::Attributes::Option.new(
75
+ name: :schema,
76
+ attribute: self,
77
+ validation_class: Servactory::Inputs::Validations::Type,
78
+ define_methods: [
79
+ Servactory::Maintenance::Attributes::DefineMethod.new(
80
+ name: :hash_mode?,
81
+ content: ->(**) { hash_mode_class_names.include?(options.fetch(:type)) }
82
+ )
83
+ ],
84
+ need_for_checks: false,
85
+ body_key: :is,
86
+ body_fallback: {},
87
+ **options
88
+ )
89
+ end
90
+
91
+ def collection_of_options
92
+ @collection_of_options ||= Servactory::Maintenance::Attributes::OptionsCollection.new
93
+ end
94
+
95
+ def options_for_checks
96
+ collection_of_options.options_for_checks
30
97
  end
31
98
  end
32
99
  end
@@ -6,7 +6,7 @@ module Servactory
6
6
  class Base
7
7
  protected
8
8
 
9
- def raise_error_with(message, **attributes)
9
+ def raise_error_with(message:, **attributes)
10
10
  message = message.call(**attributes) if message.is_a?(Proc)
11
11
 
12
12
  raise @context.class.config.internal_error_class.new(message: message)
@@ -4,24 +4,10 @@ module Servactory
4
4
  module Internals
5
5
  module Validations
6
6
  class Type < Base
7
- DEFAULT_MESSAGE = lambda do |service_class_name:, internal:, expected_type:, given_type:|
8
- I18n.t(
9
- "servactory.internals.checks.type.default_error",
10
- service_class_name: service_class_name,
11
- internal_name: internal.name,
12
- expected_type: expected_type,
13
- given_type: given_type
14
- )
15
- end
16
-
17
- private_constant :DEFAULT_MESSAGE
18
-
19
7
  def self.validate!(...)
20
8
  new(...).validate!
21
9
  end
22
10
 
23
- ##########################################################################
24
-
25
11
  def initialize(context:, internal:, value:)
26
12
  super()
27
13
 
@@ -31,37 +17,14 @@ module Servactory
31
17
  end
32
18
 
33
19
  def validate!
34
- return unless should_be_checked?
35
-
36
- return if prepared_types.any? { |type| @value.is_a?(type) }
37
-
38
- raise_error_with(
39
- DEFAULT_MESSAGE,
40
- service_class_name: @context.class.name,
41
- internal: @internal,
42
- expected_type: prepared_types.join(", "),
43
- given_type: @value.class.name
20
+ Servactory::Maintenance::Validations::Types.validate!(
21
+ context: @context,
22
+ attribute: @internal,
23
+ types: @internal.types,
24
+ value: @value,
25
+ error_callback: ->(**args) { raise_error_with(**args) }
44
26
  )
45
27
  end
46
-
47
- private
48
-
49
- def should_be_checked?
50
- @internal.required? || (
51
- @internal.optional? && !@value.nil?
52
- )
53
- end
54
-
55
- def prepared_types
56
- @prepared_types ||=
57
- Array(@internal.types).map do |type|
58
- if type.is_a?(String)
59
- Object.const_get(type)
60
- else
61
- type
62
- end
63
- end
64
- end
65
28
  end
66
29
  end
67
30
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Maintenance
5
+ module Attributes
6
+ class DefineConflict
7
+ attr_reader :content
8
+
9
+ def initialize(content:)
10
+ @content = content
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Maintenance
5
+ module Attributes
6
+ class DefineMethod
7
+ attr_reader :name,
8
+ :content
9
+
10
+ def initialize(name:, content:)
11
+ @name = name.to_sym
12
+ @content = content
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Maintenance
5
+ module Attributes
6
+ class Option
7
+ DEFAULT_BODY = ->(key:, body:, message: nil) { { key => body, message: message } }
8
+
9
+ private_constant :DEFAULT_BODY
10
+
11
+ attr_reader :name,
12
+ :validation_class,
13
+ :define_methods,
14
+ :define_conflicts,
15
+ :need_for_checks,
16
+ :body
17
+
18
+ # rubocop:disable Metrics/MethodLength
19
+ def initialize(
20
+ name:,
21
+ attribute:,
22
+ validation_class:,
23
+ need_for_checks:,
24
+ body_fallback:,
25
+ original_value: nil,
26
+ body_key: nil,
27
+ body_value: true,
28
+ define_methods: nil,
29
+ define_conflicts: nil,
30
+ with_advanced_mode: true,
31
+ **options
32
+ ) # do
33
+ @name = name.to_sym
34
+ @validation_class = validation_class
35
+ @define_methods = define_methods
36
+ @define_conflicts = define_conflicts
37
+ @need_for_checks = need_for_checks
38
+
39
+ @body = prepare_value_for(
40
+ original_value: original_value,
41
+ options: options,
42
+ body_key: body_key,
43
+ body_value: body_value,
44
+ body_fallback: body_fallback,
45
+ with_advanced_mode: with_advanced_mode
46
+ )
47
+
48
+ prepare_methods_for(attribute)
49
+ end
50
+ # rubocop:enable Metrics/MethodLength
51
+
52
+ def need_for_checks?
53
+ need_for_checks
54
+ end
55
+
56
+ private
57
+
58
+ def prepare_value_for(
59
+ original_value:,
60
+ options:,
61
+ body_key:,
62
+ body_value:,
63
+ body_fallback:,
64
+ with_advanced_mode:
65
+ )
66
+ return original_value if original_value.present?
67
+
68
+ return options.fetch(@name, body_fallback) unless with_advanced_mode
69
+
70
+ prepare_advanced_for(
71
+ body: options.fetch(@name, DEFAULT_BODY.call(key: body_key, body: body_fallback)),
72
+ body_key: body_key,
73
+ body_value: body_value,
74
+ body_fallback: body_fallback
75
+ )
76
+ end
77
+
78
+ # rubocop:disable Metrics/MethodLength
79
+ def prepare_advanced_for(
80
+ body:,
81
+ body_key:,
82
+ body_value:,
83
+ body_fallback:
84
+ )
85
+ if body.is_a?(Hash)
86
+ if @name == :schema && body.fetch(body_key, nil).nil?
87
+ DEFAULT_BODY.call(key: body_key, body: body)
88
+ else
89
+ message = body.fetch(:message, nil)
90
+
91
+ DEFAULT_BODY.call(
92
+ key: body_key,
93
+ body: body.fetch(body_key, message.present? ? body_value : body_fallback),
94
+ message: message
95
+ )
96
+ end
97
+ else
98
+ DEFAULT_BODY.call(key: body_key, body: body)
99
+ end
100
+ end
101
+ # rubocop:enable Metrics/MethodLength
102
+
103
+ def prepare_methods_for(attribute)
104
+ attribute.instance_eval(define_methods_template) if define_methods_template.present?
105
+ end
106
+
107
+ def define_methods_template
108
+ return if @define_methods.blank?
109
+
110
+ @define_methods_template ||= @define_methods.map do |define_method|
111
+ <<-RUBY
112
+ def #{define_method.name}
113
+ #{define_method.content.call(option: @body)}
114
+ end
115
+ RUBY
116
+ end.join("\n")
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Maintenance
5
+ module Attributes
6
+ class OptionHelper
7
+ attr_reader :name,
8
+ :equivalent
9
+
10
+ def initialize(name:, equivalent:)
11
+ @name = name
12
+ @equivalent = equivalent
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Maintenance
5
+ module Attributes
6
+ class OptionHelpersCollection
7
+ extend Forwardable
8
+ def_delegators :@collection, :<<, :find, :merge
9
+
10
+ def initialize(collection)
11
+ @collection = collection
12
+ end
13
+
14
+ def find_by(name:)
15
+ find { |helper| helper.name == name }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Maintenance
5
+ module Attributes
6
+ class OptionsCollection
7
+ extend Forwardable
8
+ def_delegators :@collection, :<<, :filter, :each, :map, :flat_map, :find
9
+
10
+ def initialize(*)
11
+ @collection = Set.new
12
+ end
13
+
14
+ def names
15
+ map(&:name)
16
+ end
17
+
18
+ def validation_classes
19
+ filter { |option| option.validation_class.present? }.map(&:validation_class).uniq
20
+ end
21
+
22
+ def options_for_checks
23
+ filter(&:need_for_checks?).to_h do |option|
24
+ option_body = if option.body.is_a?(Hash)
25
+ option.body.key?(:is) ? option.body.fetch(:is) : option.body
26
+ else
27
+ option.body
28
+ end
29
+
30
+ [option.name, option_body]
31
+ end
32
+ end
33
+
34
+ def defined_conflict_code
35
+ flat_map do |option|
36
+ option.define_conflicts&.map do |define_input_conflict|
37
+ define_input_conflict.content.call
38
+ end
39
+ end.reject(&:blank?).first
40
+ end
41
+
42
+ def find_by(name:)
43
+ find { |option| option.name == name }
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Maintenance
5
+ module CollectionMode
6
+ class ClassNamesCollection
7
+ extend Forwardable
8
+ def_delegators :@collection, :include?
9
+
10
+ def initialize(collection)
11
+ @collection = collection
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Maintenance
5
+ module HashMode
6
+ class ClassNamesCollection
7
+ extend Forwardable
8
+ def_delegators :@collection, :include?
9
+
10
+ def initialize(collection)
11
+ @collection = collection
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Maintenance
5
+ module Validations
6
+ class Collection
7
+ attr_reader :errors
8
+
9
+ def self.validate(...)
10
+ new(...).validate
11
+ end
12
+
13
+ def initialize(value:, types:, type:)
14
+ @value = value
15
+ @types = types
16
+ @type = type
17
+
18
+ @errors = []
19
+ end
20
+
21
+ def validate
22
+ unless @value.is_a?(prepared_type)
23
+ add_error(
24
+ expected_type: prepared_type.name,
25
+ given_type: @value.class.name
26
+ )
27
+
28
+ return self
29
+ end
30
+
31
+ validate_value!
32
+
33
+ self
34
+ end
35
+
36
+ def valid?
37
+ @errors.empty?
38
+ end
39
+
40
+ private
41
+
42
+ def prepared_type
43
+ @prepared_type ||= @types.fetch(0, Array)
44
+ end
45
+
46
+ def validate_value!
47
+ @value.each do |value_item|
48
+ next if value_item.is_a?(@type)
49
+
50
+ add_error(
51
+ expected_type: @type,
52
+ given_type: value_item.class.name
53
+ )
54
+ end
55
+ end
56
+
57
+ def add_error(expected_type:, given_type:)
58
+ @errors << {
59
+ expected_type: expected_type,
60
+ given_type: given_type
61
+ }
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end