servactory 3.0.0.rc5 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 424fe07b12c6257356afa89f41e8eb1c8f093d41a97038c2ea099fbf5b971d0b
4
- data.tar.gz: 2dceeed7832dbbbe9ed5826ddd6cb52e8af9950c255c81313906fb4c2c86bae1
3
+ metadata.gz: 1b84875a142c1878a68ea71f3874019a8028bc8eff3836706d3079107b06761b
4
+ data.tar.gz: 2a47fd738513716831e2fd491266e1c122a1200bcff9737d90a47087e95f2f64
5
5
  SHA512:
6
- metadata.gz: d5c6d1f2b57fdffe0cd823b2ad53b405213107b6501c5cef29fc08143406929e87abee5d1689c3ec34b5fc7340c6555118a6ee2919167abc0a3efa2e551e6e34
7
- data.tar.gz: 2a3c17b42d9a31edf32f11f63dbc102b511e0957b778ecffe21ff0b4374e8c5a18c68ed79092f3529d4553865ab7eb86e1007fec3671e842ff2406d2c80b811a
6
+ metadata.gz: 502fdff740f4a46378ee1b8664279fbc2cebfb7fe4fa01025a30499d3504ae1ae84b1ead432e28b1e23d59a572ba685690c88e681633bcb02020df5756e6328d
7
+ data.tar.gz: 14482adc188d556373eaa482502f2bd59533ca5a8e3d6b590109cb6cf18755c9ae34a77df79baa7d654fd0657b7202821d2983447c8485525b62445bd4ac7898
@@ -13,6 +13,10 @@ module Servactory
13
13
  end
14
14
  private_constant :STROMA
15
15
 
16
+ # DEPRECATED: This module is retained for backward compatibility only.
17
+ # It will be removed in a future major version.
18
+ # Use the Stroma-based `extensions do...end` block DSL instead,
19
+ # which provides proper per-class isolation and thread-safe hook management.
16
20
  module Extensions
17
21
  def self.registry
18
22
  @registry ||= []
@@ -33,6 +37,14 @@ module Servactory
33
37
  Extensions.registry.each { |extension| base.include(extension) }
34
38
  end
35
39
 
40
+ # DEPRECATED: This method is retained for backward compatibility only.
41
+ # It will be removed in a future major version.
42
+ # Use the Stroma-based `extensions do...end` block DSL instead.
43
+ #
44
+ # WARNING: This method mutates global shared state (Extensions.registry),
45
+ # which is not thread-safe. The `extensions do...end` mechanism
46
+ # stores hooks per-class with deep copying on inheritance, ensuring
47
+ # proper isolation across different base classes and gems.
36
48
  def self.with_extensions(*extensions)
37
49
  Extensions.clear
38
50
  Extensions.register(*extensions)
@@ -23,6 +23,26 @@ module Servactory
23
23
  @type == normalize_method_name(name) || super
24
24
  end
25
25
 
26
+ # Pattern matching support for nested error matching.
27
+ #
28
+ # Returns hash of error attributes for use with case/in.
29
+ #
30
+ # @param keys [Array<Symbol>, nil] Keys to include, or nil for all
31
+ # @return [Hash<Symbol, Object>] Hash with type, message, meta
32
+ #
33
+ # @example Nested matching in Result
34
+ # case result
35
+ # in { failure: true, error: { type: :validation, message: } }
36
+ # flash[:error] = message
37
+ # end
38
+ def deconstruct_keys(keys)
39
+ available = { type: @type, message: @message, meta: @meta }
40
+
41
+ return available if keys.nil?
42
+
43
+ available.slice(*keys)
44
+ end
45
+
26
46
  private
27
47
 
28
48
  def normalize_method_name(name)
@@ -148,7 +148,7 @@ module Servactory
148
148
  options.merge(
149
149
  actor:,
150
150
  types: attribute.types,
151
- must: must&.body
151
+ must: must&.value
152
152
  )
153
153
  end
154
154
  end
@@ -13,7 +13,8 @@ module Servactory
13
13
  :define_methods,
14
14
  :define_conflicts,
15
15
  :need_for_checks,
16
- :body
16
+ :body,
17
+ :body_key
17
18
 
18
19
  # rubocop:disable Metrics/MethodLength
19
20
  def initialize(
@@ -23,7 +24,7 @@ module Servactory
23
24
  need_for_checks:,
24
25
  body_fallback:,
25
26
  original_value: nil,
26
- body_key: nil,
27
+ body_key: :is,
27
28
  body_value: true,
28
29
  define_methods: nil,
29
30
  define_conflicts: nil,
@@ -31,6 +32,7 @@ module Servactory
31
32
  **options
32
33
  )
33
34
  @name = name.to_sym
35
+ @body_key = body_key
34
36
  @validation_class = validation_class
35
37
  @define_methods = define_methods
36
38
  @define_conflicts = define_conflicts
@@ -49,6 +51,12 @@ module Servactory
49
51
  end
50
52
  # rubocop:enable Metrics/MethodLength
51
53
 
54
+ def value
55
+ return body unless body.is_a?(Hash)
56
+
57
+ body.fetch(@body_key, body)
58
+ end
59
+
52
60
  def need_for_checks?
53
61
  need_for_checks
54
62
  end
@@ -79,6 +79,7 @@ module Servactory
79
79
  validation_class:,
80
80
  original_value: Array(@options.fetch(:type)).uniq,
81
81
  need_for_checks: true,
82
+ body_key: :is,
82
83
  body_fallback: nil,
83
84
  with_advanced_mode: false
84
85
  )
@@ -95,6 +96,7 @@ module Servactory
95
96
  )
96
97
  ],
97
98
  need_for_checks: true,
99
+ body_key: :is,
98
100
  body_fallback: nil,
99
101
  with_advanced_mode: false
100
102
  )
@@ -108,12 +108,9 @@ module Servactory
108
108
  # Extracts the normalized body value from an option.
109
109
  #
110
110
  # @param option [Option] the option to extract from
111
- # @return [Object] the :is value if body is a Hash with :is key, otherwise the full body
111
+ # @return [Object] the body_key value if body is a Hash, otherwise the full body
112
112
  def extract_normalized_body_from(option:)
113
- body = option.body
114
- return body unless body.is_a?(Hash)
115
-
116
- body.key?(:is) ? body.fetch(:is) : body
113
+ option.value
117
114
  end
118
115
 
119
116
  # Resolves conflict codes from an option's define_conflicts.
@@ -70,7 +70,7 @@ module Servactory
70
70
  # when predicate_methods_enabled is true.
71
71
  #
72
72
  # @param name [Symbol] Method name (output or predicate)
73
- # @param args [Array] Method arguments (unused)
73
+ # @param args [Array] Method arguments
74
74
  # @return [Object] Output value or predicate result
75
75
  def method_missing(name, *args)
76
76
  if name.to_s.end_with?("?")
@@ -133,9 +133,6 @@ module Servactory
133
133
 
134
134
  ############################################################################
135
135
 
136
- STATE_PREDICATE_NAMES = %i[success? failure?].freeze
137
- private_constant :STATE_PREDICATE_NAMES
138
-
139
136
  # Creates a success result for the given context.
140
137
  #
141
138
  # @param context [Object] Service execution context with outputs
@@ -222,6 +219,40 @@ module Servactory
222
219
  outputs.send(:output_names).to_h { |key| [key, outputs.public_send(key)] }.compact
223
220
  end
224
221
 
222
+ # Pattern matching support.
223
+ #
224
+ # Returns hash of result state and output values for use with case/in.
225
+ # State keys (:success, :failure, :error) take priority over output names.
226
+ #
227
+ # @param keys [Array<Symbol>, nil] Keys to include, or nil for all
228
+ # @return [Hash<Symbol, Object>] Hash of state and outputs for pattern matching
229
+ #
230
+ # @example Basic matching
231
+ # case result
232
+ # in { success: true, user: }
233
+ # redirect_to user
234
+ # in { failure: true }
235
+ # render :error
236
+ # end
237
+ #
238
+ # @example Matching with error details
239
+ # case result
240
+ # in { failure: true, error: { type: :validation, message: } }
241
+ # flash[:error] = message
242
+ # end
243
+ def deconstruct_keys(keys)
244
+ available = { success: success?, failure: failure? }
245
+ available[:error] = error if failure?
246
+
247
+ outputs.send(:output_names).each do |name|
248
+ available[name] = outputs.public_send(name)
249
+ end
250
+
251
+ return available if keys.nil?
252
+
253
+ available.slice(*keys)
254
+ end
255
+
225
256
  # Returns string representation for debugging.
226
257
  #
227
258
  # @return [String] Formatted result state and outputs
@@ -5,7 +5,7 @@ module Servactory
5
5
  MAJOR = 3
6
6
  MINOR = 0
7
7
  PATCH = 0
8
- PRE = "rc5"
8
+ PRE = nil
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH, PRE].compact.join(".")
11
11
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: servactory
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.rc5
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton Sokolov
@@ -354,7 +354,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
354
354
  - !ruby/object:Gem::Version
355
355
  version: '0'
356
356
  requirements: []
357
- rubygems_version: 3.6.9
357
+ rubygems_version: 4.0.4
358
358
  specification_version: 4
359
359
  summary: A set of tools for building reliable services of any complexity
360
360
  test_files: []