servactory 2.16.1 → 3.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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -9
  3. data/config/locales/de.yml +134 -0
  4. data/config/locales/en.yml +15 -0
  5. data/config/locales/es.yml +134 -0
  6. data/config/locales/fr.yml +134 -0
  7. data/config/locales/it.yml +134 -0
  8. data/config/locales/ru.yml +15 -0
  9. data/lib/generators/README.md +45 -0
  10. data/lib/generators/servactory/base.rb +82 -0
  11. data/lib/generators/servactory/extension/USAGE +54 -0
  12. data/lib/generators/servactory/extension/extension_generator.rb +41 -0
  13. data/lib/generators/servactory/extension/templates/extension.rb.tt +62 -0
  14. data/lib/generators/servactory/install/USAGE +27 -0
  15. data/lib/generators/servactory/install/install_generator.rb +94 -0
  16. data/lib/generators/servactory/{templates/services/application_service/base.rb → install/templates/application_service/base.rb.tt} +29 -19
  17. data/lib/generators/servactory/{templates/services/application_service/exceptions.rb → install/templates/application_service/exceptions.rb.tt} +1 -1
  18. data/lib/generators/servactory/{templates/services/application_service/result.rb → install/templates/application_service/result.rb.tt} +1 -1
  19. data/lib/generators/servactory/rspec/USAGE +46 -0
  20. data/lib/generators/servactory/rspec/rspec_generator.rb +95 -0
  21. data/lib/generators/servactory/rspec/templates/service_spec.rb.tt +58 -0
  22. data/lib/generators/servactory/service/USAGE +51 -0
  23. data/lib/generators/servactory/service/service_generator.rb +56 -0
  24. data/lib/generators/servactory/service/templates/service.rb.tt +22 -0
  25. data/lib/servactory/actions/collection.rb +56 -1
  26. data/lib/servactory/actions/dsl.rb +11 -11
  27. data/lib/servactory/actions/tools/rules.rb +1 -1
  28. data/lib/servactory/actions/tools/runner.rb +111 -28
  29. data/lib/servactory/base.rb +1 -7
  30. data/lib/servactory/configuration/actions/aliases/collection.rb +5 -0
  31. data/lib/servactory/configuration/actions/rescue_handlers/collection.rb +5 -0
  32. data/lib/servactory/configuration/actions/shortcuts/collection.rb +5 -0
  33. data/lib/servactory/configuration/collection_mode/class_names_collection.rb +5 -0
  34. data/lib/servactory/configuration/config.rb +36 -0
  35. data/lib/servactory/configuration/configurable.rb +95 -0
  36. data/lib/servactory/configuration/dsl.rb +3 -27
  37. data/lib/servactory/configuration/factory.rb +20 -20
  38. data/lib/servactory/configuration/hash_mode/class_names_collection.rb +5 -0
  39. data/lib/servactory/configuration/option_helpers/option_helpers_collection.rb +5 -0
  40. data/lib/servactory/context/warehouse/inputs.rb +2 -2
  41. data/lib/servactory/context/workspace/inputs.rb +2 -2
  42. data/lib/servactory/context/workspace/internals.rb +2 -2
  43. data/lib/servactory/context/workspace/outputs.rb +2 -2
  44. data/lib/servactory/context/workspace.rb +11 -7
  45. data/lib/servactory/dsl.rb +10 -8
  46. data/lib/servactory/maintenance/attributes/tools/validation.rb +1 -1
  47. data/lib/servactory/result.rb +2 -2
  48. data/lib/servactory/test_kit/fake_type.rb +23 -0
  49. data/lib/servactory/test_kit/result.rb +45 -0
  50. data/lib/servactory/test_kit/rspec/helpers/argument_matchers.rb +97 -0
  51. data/lib/servactory/test_kit/rspec/helpers/concerns/error_messages.rb +179 -0
  52. data/lib/servactory/test_kit/rspec/helpers/concerns/service_class_validation.rb +74 -0
  53. data/lib/servactory/test_kit/rspec/helpers/fluent.rb +110 -0
  54. data/lib/servactory/test_kit/rspec/helpers/input_validator.rb +149 -0
  55. data/lib/servactory/test_kit/rspec/helpers/legacy.rb +228 -0
  56. data/lib/servactory/test_kit/rspec/helpers/mock_executor.rb +256 -0
  57. data/lib/servactory/test_kit/rspec/helpers/output_validator.rb +121 -0
  58. data/lib/servactory/test_kit/rspec/helpers/service_mock_builder.rb +422 -0
  59. data/lib/servactory/test_kit/rspec/helpers/service_mock_config.rb +129 -0
  60. data/lib/servactory/test_kit/rspec/helpers.rb +51 -84
  61. data/lib/servactory/test_kit/rspec/matchers/base/attribute_matcher.rb +324 -0
  62. data/lib/servactory/test_kit/rspec/matchers/base/submatcher.rb +133 -0
  63. data/lib/servactory/test_kit/rspec/matchers/base/submatcher_context.rb +101 -0
  64. data/lib/servactory/test_kit/rspec/matchers/base/submatcher_registry.rb +205 -0
  65. data/lib/servactory/test_kit/rspec/matchers/concerns/attribute_data_access.rb +100 -0
  66. data/lib/servactory/test_kit/rspec/matchers/concerns/error_message_builder.rb +106 -0
  67. data/lib/servactory/test_kit/rspec/matchers/concerns/value_comparison.rb +97 -0
  68. data/lib/servactory/test_kit/rspec/matchers/have_service_input_matcher.rb +89 -219
  69. data/lib/servactory/test_kit/rspec/matchers/have_service_internal_matcher.rb +74 -166
  70. data/lib/servactory/test_kit/rspec/matchers/have_service_output_matcher.rb +238 -0
  71. data/lib/servactory/test_kit/rspec/matchers/result/be_failure_service_matcher.rb +257 -0
  72. data/lib/servactory/test_kit/rspec/matchers/result/be_success_service_matcher.rb +185 -0
  73. data/lib/servactory/test_kit/rspec/matchers/submatchers/input/default_submatcher.rb +81 -0
  74. data/lib/servactory/test_kit/rspec/matchers/submatchers/input/optional_submatcher.rb +62 -0
  75. data/lib/servactory/test_kit/rspec/matchers/submatchers/input/required_submatcher.rb +93 -0
  76. data/lib/servactory/test_kit/rspec/matchers/submatchers/input/valid_with_submatcher.rb +271 -0
  77. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/consists_of_submatcher.rb +85 -0
  78. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/inclusion_submatcher.rb +120 -0
  79. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/message_submatcher.rb +115 -0
  80. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/must_submatcher.rb +82 -0
  81. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/schema_submatcher.rb +102 -0
  82. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/target_submatcher.rb +125 -0
  83. data/lib/servactory/test_kit/rspec/matchers/submatchers/shared/types_submatcher.rb +77 -0
  84. data/lib/servactory/test_kit/rspec/matchers.rb +126 -285
  85. data/lib/servactory/test_kit/utils/faker.rb +62 -2
  86. data/lib/servactory/tool_kit/dynamic_options/consists_of.rb +166 -0
  87. data/lib/servactory/tool_kit/dynamic_options/format.rb +195 -8
  88. data/lib/servactory/tool_kit/dynamic_options/inclusion.rb +219 -17
  89. data/lib/servactory/tool_kit/dynamic_options/max.rb +143 -0
  90. data/lib/servactory/tool_kit/dynamic_options/min.rb +143 -0
  91. data/lib/servactory/tool_kit/dynamic_options/multiple_of.rb +157 -8
  92. data/lib/servactory/tool_kit/dynamic_options/must.rb +194 -0
  93. data/lib/servactory/tool_kit/dynamic_options/schema.rb +226 -2
  94. data/lib/servactory/tool_kit/dynamic_options/target.rb +248 -0
  95. data/lib/servactory/version.rb +4 -4
  96. data/lib/servactory.rb +6 -0
  97. metadata +57 -48
  98. data/lib/generators/servactory/install_generator.rb +0 -21
  99. data/lib/generators/servactory/rspec_generator.rb +0 -88
  100. data/lib/generators/servactory/service_generator.rb +0 -49
  101. data/lib/servactory/configuration/setup.rb +0 -97
  102. data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/consists_of_matcher.rb +0 -68
  103. data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/inclusion_matcher.rb +0 -73
  104. data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/message_matcher.rb +0 -91
  105. data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/must_matcher.rb +0 -72
  106. data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/schema_matcher.rb +0 -92
  107. data/lib/servactory/test_kit/rspec/matchers/have_service_attribute_matchers/types_matcher.rb +0 -72
  108. data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/default_matcher.rb +0 -69
  109. data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/optional_matcher.rb +0 -63
  110. data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/required_matcher.rb +0 -81
  111. data/lib/servactory/test_kit/rspec/matchers/have_service_input_matchers/valid_with_matcher.rb +0 -199
@@ -3,16 +3,48 @@
3
3
  module Servactory
4
4
  module Actions
5
5
  module Tools
6
+ # Executes service actions within stages.
7
+ #
8
+ # ## Purpose
9
+ #
10
+ # Orchestrates the execution of service actions, handling stage wrappers,
11
+ # rollbacks, and conditional execution (only_if/only_unless). Provides
12
+ # the core execution engine for Servactory services.
13
+ #
14
+ # ## Usage
15
+ #
16
+ # ```ruby
17
+ # Runner.run!(context, collection_of_stages)
18
+ # ```
19
+ #
20
+ # ## Integration
21
+ #
22
+ # Called by Servactory::Context::Callable to execute all actions
23
+ # defined in a service. Works with Stages::Collection and Actions::Collection.
6
24
  class Runner
25
+ # Runs the service actions.
26
+ #
27
+ # @param context [Object] The service context
28
+ # @param collection_of_stages [Stages::Collection] The stages to execute
29
+ # @return [void]
7
30
  def self.run!(...)
8
31
  new(...).run!
9
32
  end
10
33
 
34
+ # Creates a new runner instance.
35
+ #
36
+ # @param context [Object] The service context with inputs/internals/outputs
37
+ # @param collection_of_stages [Stages::Collection] Collection of stages to execute
11
38
  def initialize(context, collection_of_stages)
12
39
  @context = context
13
40
  @collection_of_stages = collection_of_stages
14
41
  end
15
42
 
43
+ # Executes all stages in position order.
44
+ #
45
+ # Falls back to calling the service's `call` method if no stages defined.
46
+ #
47
+ # @return [void]
16
48
  def run!
17
49
  return use_call if @collection_of_stages.empty?
18
50
 
@@ -23,24 +55,42 @@ module Servactory
23
55
 
24
56
  private
25
57
 
58
+ # Falls back to the service's call method when no stages defined.
59
+ #
60
+ # @return [void]
26
61
  def use_call
27
62
  @context.send(:call)
28
63
  end
29
64
 
65
+ # Executes a single stage with its actions.
66
+ #
67
+ # Handles wrapper execution, rollbacks, and conditional skipping.
68
+ #
69
+ # @param stage [Stages::Stage] The stage to execute
70
+ # @return [void]
30
71
  def call_stage(stage)
31
- return if unnecessary_for_stage?(stage)
72
+ return if should_skip?(stage)
32
73
 
33
- wrapper = stage.wrapper
34
- rollback = stage.rollback
35
74
  actions = stage.actions.sorted_by_position
36
75
 
37
- if wrapper.is_a?(Proc)
38
- call_wrapper_with_actions(wrapper, rollback, actions)
76
+ if stage.wrapper.is_a?(Proc)
77
+ call_wrapper_with_actions(stage.wrapper, stage.rollback, actions)
78
+ elsif stage.rollback.present?
79
+ call_actions_with_rollback(stage.rollback, actions)
39
80
  else
40
81
  call_actions(actions)
41
82
  end
42
83
  end
43
84
 
85
+ # Executes actions within a wrapper proc.
86
+ #
87
+ # Handles exceptions by calling rollback if defined,
88
+ # otherwise fails the service with the exception details.
89
+ #
90
+ # @param wrapper [Proc] The wrapper proc (e.g., transaction block)
91
+ # @param rollback [Symbol, nil] Optional rollback method name
92
+ # @param actions [Collection] Actions to execute within wrapper
93
+ # @return [void]
44
94
  def call_wrapper_with_actions(wrapper, rollback, actions) # rubocop:disable Metrics/MethodLength
45
95
  wrapper.call(methods: -> { call_actions(actions) }, context: @context)
46
96
  rescue StandardError => e
@@ -56,47 +106,80 @@ module Servactory
56
106
  end
57
107
  end
58
108
 
109
+ # Executes actions with rollback support but no wrapper.
110
+ #
111
+ # If an exception occurs, calls the rollback method with the exception.
112
+ #
113
+ # @param rollback [Symbol] The rollback method name
114
+ # @param actions [Collection] Actions to execute
115
+ # @return [void]
116
+ def call_actions_with_rollback(rollback, actions)
117
+ call_actions(actions)
118
+ rescue StandardError => e
119
+ @context.send(rollback, e)
120
+ end
121
+
122
+ # Executes a collection of actions in order.
123
+ #
124
+ # @param actions [Collection] Actions to execute
125
+ # @return [void]
59
126
  def call_actions(actions)
60
127
  actions.each do |action|
61
- next if unnecessary_for_make?(action)
128
+ next if should_skip?(action)
62
129
 
63
130
  call_action(action)
64
131
  end
65
132
  end
66
133
 
134
+ # Executes a single action by name.
135
+ #
136
+ # @param action [Action] The action to execute
137
+ # @return [void]
138
+ # @raise [StandardError] Re-raises unless handled by rescue handler
67
139
  def call_action(action)
68
140
  @context.send(action.name)
69
141
  rescue StandardError => e
70
142
  rescue_with_handler(e) || raise
71
143
  end
72
144
 
73
- def unnecessary_for_stage?(stage)
74
- condition = stage.condition
75
- is_condition_opposite = stage.is_condition_opposite
76
-
77
- result = checks_passed_for?(condition)
78
-
79
- is_condition_opposite ? !result : result
80
- end
81
-
82
- def unnecessary_for_make?(make_action)
83
- condition = make_action.condition
84
- is_condition_opposite = make_action.is_condition_opposite
85
-
86
- result = checks_passed_for?(condition)
87
-
88
- is_condition_opposite ? !result : result
145
+ # Determines if an entity (stage or action) should be skipped.
146
+ #
147
+ # Uses the entity's condition and is_condition_opposite flag:
148
+ # - only_if: skips if condition is NOT met
149
+ # - only_unless: skips if condition IS met
150
+ #
151
+ # @param entity [Stages::Stage, Action] The entity to check
152
+ # @return [Boolean] true if entity should be skipped
153
+ def should_skip?(entity)
154
+ condition_result = condition_met?(entity.condition)
155
+
156
+ # only_if (is_condition_opposite = false): skip if condition is NOT met
157
+ # only_unless (is_condition_opposite = true): skip if condition IS met
158
+ entity.is_condition_opposite ? condition_result : !condition_result
89
159
  end
90
160
 
91
- def checks_passed_for?(condition)
92
- return false if condition.nil?
93
- return !Servactory::Utils.true?(condition) unless condition.is_a?(Proc)
94
-
95
- !condition.call(context: @context)
161
+ # Evaluates a condition value.
162
+ #
163
+ # Handles nil (always true), boolean, and Proc conditions.
164
+ #
165
+ # @param condition [Proc, Boolean, nil] The condition to evaluate
166
+ # @return [Boolean] true if condition is met
167
+ def condition_met?(condition)
168
+ return true if condition.nil?
169
+
170
+ if condition.is_a?(Proc)
171
+ condition.call(context: @context)
172
+ else
173
+ Servactory::Utils.true?(condition)
174
+ end
96
175
  end
97
176
 
177
+ # Attempts to handle an exception with configured rescue handlers.
178
+ #
179
+ # @param exception [Exception] The exception to handle
180
+ # @return [Exception, nil] The exception if handled, nil otherwise
98
181
  def rescue_with_handler(exception) # rubocop:disable Metrics/MethodLength
99
- _, handler = @context.class.config.action_rescue_handlers.reverse_each.detect do |class_or_name, _|
182
+ _, handler = @context.config.action_rescue_handlers.reverse_each.detect do |class_or_name, _|
100
183
  if (detected_exception = Servactory::Utils.constantize_class(class_or_name))
101
184
  detected_exception === exception # rubocop:disable Style/CaseEquality
102
185
  end
@@ -2,13 +2,7 @@
2
2
 
3
3
  module Servactory
4
4
  class Base
5
- include Configuration::DSL
6
- include Info::DSL
7
- include Context::DSL
8
- include Inputs::DSL
9
- include Internals::DSL
10
- include Outputs::DSL
11
- include Actions::DSL
5
+ include Servactory::DSL
12
6
 
13
7
  private_class_method :new
14
8
  end
@@ -12,6 +12,11 @@ module Servactory
12
12
  def initialize(*)
13
13
  @collection = Set.new
14
14
  end
15
+
16
+ def initialize_dup(original)
17
+ super
18
+ @collection = original.instance_variable_get(:@collection).dup
19
+ end
15
20
  end
16
21
  end
17
22
  end
@@ -12,6 +12,11 @@ module Servactory
12
12
  def initialize(*)
13
13
  @collection = Set.new
14
14
  end
15
+
16
+ def initialize_dup(original)
17
+ super
18
+ @collection = original.instance_variable_get(:@collection).dup
19
+ end
15
20
  end
16
21
  end
17
22
  end
@@ -13,6 +13,11 @@ module Servactory
13
13
  @collection = {}
14
14
  end
15
15
 
16
+ def initialize_dup(original)
17
+ super
18
+ @collection = original.instance_variable_get(:@collection).dup
19
+ end
20
+
16
21
  alias merge merge!
17
22
 
18
23
  def shortcuts
@@ -11,6 +11,11 @@ module Servactory
11
11
  def initialize(collection)
12
12
  @collection = collection
13
13
  end
14
+
15
+ def initialize_dup(original)
16
+ super
17
+ @collection = original.instance_variable_get(:@collection).dup
18
+ end
14
19
  end
15
20
  end
16
21
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Configuration
5
+ class Config
6
+ attr_accessor :input_exception_class,
7
+ :internal_exception_class,
8
+ :output_exception_class,
9
+ :failure_class,
10
+ :success_class,
11
+ :result_class,
12
+ :action_shortcuts,
13
+ :action_aliases,
14
+ :input_option_helpers,
15
+ :internal_option_helpers,
16
+ :output_option_helpers,
17
+ :collection_mode_class_names,
18
+ :hash_mode_class_names,
19
+ :action_rescue_handlers,
20
+ :i18n_root_key,
21
+ :predicate_methods_enabled
22
+
23
+ def initialize_dup(original) # rubocop:disable Metrics/AbcSize
24
+ super
25
+ @action_shortcuts = original.action_shortcuts.dup
26
+ @action_aliases = original.action_aliases.dup
27
+ @input_option_helpers = original.input_option_helpers.dup
28
+ @internal_option_helpers = original.internal_option_helpers.dup
29
+ @output_option_helpers = original.output_option_helpers.dup
30
+ @collection_mode_class_names = original.collection_mode_class_names.dup
31
+ @hash_mode_class_names = original.hash_mode_class_names.dup
32
+ @action_rescue_handlers = original.action_rescue_handlers.dup
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Servactory
4
+ module Configuration
5
+ module Configurable
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+ def self.extended(base)
12
+ base.instance_variable_set(:@config, base.send(:build_default_config))
13
+ end
14
+
15
+ attr_reader :config
16
+
17
+ private
18
+
19
+ def build_default_config # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
20
+ Config.new.tap do |config|
21
+ # NOTE: Internal (MUST be first - used by option_helpers)
22
+ config.collection_mode_class_names =
23
+ CollectionMode::ClassNamesCollection.new(default_collection_mode_class_names)
24
+ config.hash_mode_class_names =
25
+ HashMode::ClassNamesCollection.new(default_hash_mode_class_names)
26
+
27
+ # NOTE: Exception classes
28
+ config.input_exception_class = Servactory::Exceptions::Input
29
+ config.internal_exception_class = Servactory::Exceptions::Internal
30
+ config.output_exception_class = Servactory::Exceptions::Output
31
+ config.failure_class = Servactory::Exceptions::Failure
32
+ config.success_class = Servactory::Exceptions::Success
33
+
34
+ # NOTE: Result
35
+ config.result_class = Servactory::Result
36
+
37
+ # NOTE: Actions
38
+ config.action_shortcuts = Actions::Shortcuts::Collection.new
39
+ config.action_aliases = Actions::Aliases::Collection.new
40
+
41
+ # NOTE: Option helpers (uses collection_mode_class_names)
42
+ config.input_option_helpers =
43
+ OptionHelpers::OptionHelpersCollection.new(default_input_option_helpers(config))
44
+ config.internal_option_helpers =
45
+ OptionHelpers::OptionHelpersCollection.new(default_internal_option_helpers(config))
46
+ config.output_option_helpers =
47
+ OptionHelpers::OptionHelpersCollection.new(default_output_option_helpers(config))
48
+
49
+ # NOTE: Other
50
+ config.action_rescue_handlers = Actions::RescueHandlers::Collection.new
51
+ config.i18n_root_key = "servactory"
52
+ config.predicate_methods_enabled = true
53
+ end
54
+ end
55
+
56
+ def default_collection_mode_class_names
57
+ Set[Array, Set]
58
+ end
59
+
60
+ def default_hash_mode_class_names
61
+ Set[Hash]
62
+ end
63
+
64
+ def default_input_option_helpers(config)
65
+ Set[
66
+ Servactory::Maintenance::Attributes::OptionHelper
67
+ .new(name: :optional, equivalent: { required: false }),
68
+ Servactory::ToolKit::DynamicOptions::ConsistsOf
69
+ .use(collection_mode_class_names: config.collection_mode_class_names),
70
+ Servactory::ToolKit::DynamicOptions::Schema.use(default_hash_mode_class_names:),
71
+ Servactory::ToolKit::DynamicOptions::Inclusion.use
72
+ ]
73
+ end
74
+
75
+ def default_internal_option_helpers(config)
76
+ Set[
77
+ Servactory::ToolKit::DynamicOptions::ConsistsOf
78
+ .use(collection_mode_class_names: config.collection_mode_class_names),
79
+ Servactory::ToolKit::DynamicOptions::Schema.use(default_hash_mode_class_names:),
80
+ Servactory::ToolKit::DynamicOptions::Inclusion.use
81
+ ]
82
+ end
83
+
84
+ def default_output_option_helpers(config)
85
+ Set[
86
+ Servactory::ToolKit::DynamicOptions::ConsistsOf
87
+ .use(collection_mode_class_names: config.collection_mode_class_names),
88
+ Servactory::ToolKit::DynamicOptions::Schema.use(default_hash_mode_class_names:),
89
+ Servactory::ToolKit::DynamicOptions::Inclusion.use
90
+ ]
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -5,38 +5,14 @@ module Servactory
5
5
  module DSL
6
6
  def self.included(base)
7
7
  base.extend(ClassMethods)
8
+ base.include(Configurable)
8
9
  end
9
10
 
10
11
  module ClassMethods
11
- def inherited(child) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
12
+ def inherited(child)
12
13
  super
13
14
 
14
- child.config.input_exception_class = config.input_exception_class
15
- child.config.internal_exception_class = config.internal_exception_class
16
- child.config.output_exception_class = config.output_exception_class
17
-
18
- child.config.success_class = config.success_class
19
- child.config.failure_class = config.failure_class
20
-
21
- child.config.result_class = config.result_class
22
-
23
- child.config.collection_mode_class_names = config.collection_mode_class_names
24
-
25
- child.config.input_option_helpers = config.input_option_helpers
26
- child.config.internal_option_helpers = config.internal_option_helpers
27
- child.config.output_option_helpers = config.output_option_helpers
28
-
29
- child.config.action_aliases = config.action_aliases
30
- child.config.action_shortcuts = config.action_shortcuts
31
- child.config.action_rescue_handlers = config.action_rescue_handlers
32
-
33
- child.config.i18n_root_key = config.i18n_root_key
34
-
35
- child.config.predicate_methods_enabled = config.predicate_methods_enabled
36
- end
37
-
38
- def config
39
- @config ||= Servactory::Configuration::Setup.new
15
+ child.instance_variable_set(:@config, config.dup)
40
16
  end
41
17
 
42
18
  private
@@ -39,12 +39,24 @@ module Servactory
39
39
  raise_error_about_wrong_result_class_with(:result_class, result_class)
40
40
  end
41
41
 
42
- def collection_mode_class_names(collection_mode_class_names)
43
- @config.collection_mode_class_names.merge(collection_mode_class_names)
42
+ def action_shortcuts(array, hash = {}) # rubocop:disable Metrics/MethodLength
43
+ prepared = array.to_h do |action_shortcut|
44
+ [
45
+ action_shortcut,
46
+ {
47
+ prefix: action_shortcut,
48
+ suffix: nil
49
+ }
50
+ ]
51
+ end
52
+
53
+ prepared = prepared.merge(hash)
54
+
55
+ @config.action_shortcuts.merge(prepared)
44
56
  end
45
57
 
46
- def hash_mode_class_names(hash_mode_class_names)
47
- @config.hash_mode_class_names.merge(hash_mode_class_names)
58
+ def action_aliases(action_aliases)
59
+ @config.action_aliases.merge(action_aliases)
48
60
  end
49
61
 
50
62
  def input_option_helpers(input_option_helpers)
@@ -59,24 +71,12 @@ module Servactory
59
71
  @config.output_option_helpers.merge(output_option_helpers)
60
72
  end
61
73
 
62
- def action_aliases(action_aliases)
63
- @config.action_aliases.merge(action_aliases)
74
+ def collection_mode_class_names(collection_mode_class_names)
75
+ @config.collection_mode_class_names.merge(collection_mode_class_names)
64
76
  end
65
77
 
66
- def action_shortcuts(array, hash = {}) # rubocop:disable Metrics/MethodLength
67
- prepared = array.to_h do |action_shortcut|
68
- [
69
- action_shortcut,
70
- {
71
- prefix: action_shortcut,
72
- suffix: nil
73
- }
74
- ]
75
- end
76
-
77
- prepared = prepared.merge(hash)
78
-
79
- @config.action_shortcuts.merge(prepared)
78
+ def hash_mode_class_names(hash_mode_class_names)
79
+ @config.hash_mode_class_names.merge(hash_mode_class_names)
80
80
  end
81
81
 
82
82
  def i18n_root_key(value)
@@ -11,6 +11,11 @@ module Servactory
11
11
  def initialize(collection)
12
12
  @collection = collection
13
13
  end
14
+
15
+ def initialize_dup(original)
16
+ super
17
+ @collection = original.instance_variable_get(:@collection).dup
18
+ end
14
19
  end
15
20
  end
16
21
  end
@@ -12,6 +12,11 @@ module Servactory
12
12
  @collection = collection
13
13
  end
14
14
 
15
+ def initialize_dup(original)
16
+ super
17
+ @collection = original.instance_variable_get(:@collection).dup
18
+ end
19
+
15
20
  def dynamic_options
16
21
  OptionHelpersCollection.new(filter(&:dynamic_option?))
17
22
  end
@@ -21,11 +21,11 @@ module Servactory
21
21
  ##########################################################################
22
22
 
23
23
  def method_missing(name, *_args)
24
- input_name = @context.class.config.predicate_methods_enabled? ? name.to_s.chomp("?").to_sym : name
24
+ input_name = @context.config.predicate_methods_enabled ? name.to_s.chomp("?").to_sym : name
25
25
 
26
26
  input_value = @arguments.fetch(input_name) { raise_error_for(input_name) }
27
27
 
28
- if name.to_s.end_with?("?") && @context.class.config.predicate_methods_enabled?
28
+ if name.to_s.end_with?("?") && @context.config.predicate_methods_enabled
29
29
  Servactory::Utils.query_attribute(input_value)
30
30
  else
31
31
  input_value
@@ -39,7 +39,7 @@ module Servactory
39
39
 
40
40
  # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Lint/UnusedMethodArgument
41
41
  def fetch_with(name:, &block)
42
- input_name = @context.class.config.predicate_methods_enabled? ? name.to_s.chomp("?").to_sym : name
42
+ input_name = @context.config.predicate_methods_enabled ? name.to_s.chomp("?").to_sym : name
43
43
 
44
44
  input = @collection_of_inputs.find_by(name: input_name)
45
45
 
@@ -54,7 +54,7 @@ module Servactory
54
54
  input_prepare = input.prepare.fetch(:in, nil)
55
55
  input_value = input_prepare.call(value: input_value) if input_prepare.present?
56
56
 
57
- if name.to_s.end_with?("?") && @context.class.config.predicate_methods_enabled?
57
+ if name.to_s.end_with?("?") && @context.config.predicate_methods_enabled
58
58
  Servactory::Utils.query_attribute(input_value)
59
59
  else
60
60
  input_value
@@ -54,7 +54,7 @@ module Servactory
54
54
  end
55
55
 
56
56
  def fetch_with(name:, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Lint/UnusedMethodArgument
57
- internal_name = @context.class.config.predicate_methods_enabled? ? name.to_s.chomp("?").to_sym : name
57
+ internal_name = @context.config.predicate_methods_enabled ? name.to_s.chomp("?").to_sym : name
58
58
  internal = @collection_of_internals.find_by(name: internal_name)
59
59
 
60
60
  return yield if internal.nil?
@@ -67,7 +67,7 @@ module Servactory
67
67
  value: internal_value
68
68
  )
69
69
 
70
- if name.to_s.end_with?("?") && @context.class.config.predicate_methods_enabled?
70
+ if name.to_s.end_with?("?") && @context.config.predicate_methods_enabled
71
71
  Servactory::Utils.query_attribute(internal_value)
72
72
  else
73
73
  internal_value
@@ -54,14 +54,14 @@ module Servactory
54
54
  end
55
55
 
56
56
  def fetch_with(name:, &block) # rubocop:disable Metrics/AbcSize, Lint/UnusedMethodArgument
57
- output_name = @context.class.config.predicate_methods_enabled? ? name.to_s.chomp("?").to_sym : name
57
+ output_name = @context.config.predicate_methods_enabled ? name.to_s.chomp("?").to_sym : name
58
58
  output = @collection_of_outputs.find_by(name: output_name)
59
59
 
60
60
  return yield if output.nil?
61
61
 
62
62
  output_value = @context.send(:servactory_service_warehouse).fetch_output(output.name)
63
63
 
64
- if name.to_s.end_with?("?") && @context.class.config.predicate_methods_enabled?
64
+ if name.to_s.end_with?("?") && @context.config.predicate_methods_enabled
65
65
  Servactory::Utils.query_attribute(output_value)
66
66
  else
67
67
  output_value
@@ -8,7 +8,7 @@ module Servactory
8
8
 
9
9
  def initialize(context)
10
10
  @class_name = context.class.name
11
- @i18n_root_key = context.class.config.i18n_root_key
11
+ @i18n_root_key = context.config.i18n_root_key
12
12
  end
13
13
 
14
14
  def translate(key, **options)
@@ -42,11 +42,11 @@ module Servactory
42
42
  end
43
43
 
44
44
  def success!
45
- raise self.class.config.success_class.new(context: self)
45
+ raise config.success_class.new(context: self)
46
46
  end
47
47
 
48
48
  def fail_input!(input_name, message:, meta: nil)
49
- raise self.class.config.input_exception_class.new(
49
+ raise config.input_exception_class.new(
50
50
  context: self,
51
51
  input_name:,
52
52
  message:,
@@ -55,7 +55,7 @@ module Servactory
55
55
  end
56
56
 
57
57
  def fail_internal!(internal_name, message:, meta: nil)
58
- raise self.class.config.internal_exception_class.new(
58
+ raise config.internal_exception_class.new(
59
59
  context: self,
60
60
  internal_name:,
61
61
  message:,
@@ -64,7 +64,7 @@ module Servactory
64
64
  end
65
65
 
66
66
  def fail_output!(output_name, message:, meta: nil)
67
- raise self.class.config.output_exception_class.new(
67
+ raise config.output_exception_class.new(
68
68
  context: self,
69
69
  output_name:,
70
70
  message:,
@@ -73,13 +73,17 @@ module Servactory
73
73
  end
74
74
 
75
75
  def fail!(type = :base, message:, meta: nil)
76
- raise self.class.config.failure_class.new(type:, message:, meta:)
76
+ raise config.failure_class.new(type:, message:, meta:)
77
77
  end
78
78
 
79
79
  def fail_result!(service_result)
80
80
  fail!(service_result.error.type, message: service_result.error.message, meta: service_result.error.meta)
81
81
  end
82
82
 
83
+ def config
84
+ self.class.config
85
+ end
86
+
83
87
  private
84
88
 
85
89
  attr_reader :collection_of_inputs,
@@ -114,7 +118,7 @@ module Servactory
114
118
  end
115
119
 
116
120
  def call
117
- raise self.class.config.failure_class.new(
121
+ raise config.failure_class.new(
118
122
  type: :base,
119
123
  message: servactory_service_info.translate(
120
124
  "methods.call.not_used"