servactory 3.1.0.rc1 → 3.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c4398d2ffb193d4acd86b96f02871198d13d4e8b31ec96dddaa05c3966f1525
4
- data.tar.gz: bf35a15c0d771ef1c6362d573e2fbd5a04a0021cb0a80d847f37b23d5dff3b76
3
+ metadata.gz: 6a7c9b4d9ad2e7d15265ba278d740eb34e6df33590bf517a0b42d914dad46e22
4
+ data.tar.gz: 21ad5c1814f6bd2c62221057547f5388cf928fd1f937f37131dab041d6325983
5
5
  SHA512:
6
- metadata.gz: baa8f5c12c6edbf0786d807611a759f8fd54b3f087967ea981942843e3a19b2f1026f607bc52ad9c5f4dd42830216582e4e54d38bef5e00fa48dea47bbe84210
7
- data.tar.gz: c8af2b260386c4c2711a6b034bb116ad843cfb57c5e2b3181d59e9b9d38692ec562afc69bd5b33b46820c20972c0904e9921dfd1516e1576ec8622439ae1b382
6
+ metadata.gz: 9f231bf3c0662ec8285125cacd138d765622eb1ebad7e9eae5d95ae2dd84ad48f80a65783e208b3b9752e40e9bc755ca245bcf2f3b1c68b3724ca13a68d1f6a5
7
+ data.tar.gz: 8fb3f9f3bcf2a49f26d4cff76885537559ba4173c78585c2432fc7bf814a8e587303dc941c36a7992800bff1c561661cc04ae20beffbc17dac4d5a0af64de387
@@ -29,55 +29,42 @@ module Servactory
29
29
  @arguments.keys
30
30
  end
31
31
 
32
- # Merges new arguments into storage and defines accessor methods.
32
+ # Merges new arguments into storage.
33
33
  #
34
34
  # @param arguments [Hash] Input name-value pairs to merge
35
- # @return [void]
35
+ # @return [Hash] Updated arguments hash
36
36
  def merge!(arguments)
37
37
  @arguments.merge!(arguments)
38
- define_methods_for!(arguments)
39
38
  end
40
39
 
41
- # Raises error for any method call not pre-defined as a singleton accessor.
40
+ # Delegates method calls to stored inputs.
42
41
  #
43
42
  # Supports predicate methods when enabled in config.
44
43
  #
45
44
  # @param name [Symbol] Method name (input or predicate)
46
45
  # @param _args [Array] Method arguments (unused)
47
- # @raise [Exception] Failure exception for undefined input
46
+ # @return [Object] Input value or predicate result
48
47
  def method_missing(name, *_args)
49
48
  predicate = @context.config.predicate_methods_enabled && name.end_with?("?")
49
+
50
50
  input_name = predicate ? name.to_s.chomp("?").to_sym : name
51
- raise_error_for(input_name)
51
+
52
+ input_value = @arguments.fetch(input_name) { raise_error_for(input_name) }
53
+
54
+ predicate ? Servactory::Utils.query_attribute(input_value) : input_value
52
55
  end
53
56
 
54
- # Returns false since all valid methods are defined as singleton methods.
57
+ # Checks if method corresponds to stored input.
55
58
  #
56
- # @return [Boolean] Always false
57
- def respond_to_missing?(*)
58
- false
59
+ # @param name [Symbol] Method name to check
60
+ # @return [Boolean] True if input exists for this method
61
+ def respond_to_missing?(name, *)
62
+ input_name = name.to_s.chomp("?").to_sym
63
+ @arguments.key?(input_name) || @arguments.key?(name) || super
59
64
  end
60
65
 
61
66
  private
62
67
 
63
- # Defines singleton accessor methods for given arguments.
64
- #
65
- # @param arguments [Hash] Input name-value pairs to define methods for
66
- # @return [void]
67
- def define_methods_for!(arguments)
68
- arguments.each_key do |name|
69
- define_singleton_method(name) do
70
- @arguments.fetch(name) { raise_error_for(name) }
71
- end
72
-
73
- next unless @context.config.predicate_methods_enabled
74
-
75
- define_singleton_method(:"#{name}?") do
76
- Servactory::Utils.query_attribute(@arguments.fetch(name) { raise_error_for(name) })
77
- end
78
- end
79
- end
80
-
81
68
  # Raises error for undefined input.
82
69
  #
83
70
  # @param input_name [Symbol] Name of undefined input
@@ -7,8 +7,6 @@ module Servactory
7
7
  def initialize(context:, collection_of_inputs:)
8
8
  @context = context
9
9
  @collection_of_inputs = collection_of_inputs
10
-
11
- define_attribute_methods!
12
10
  end
13
11
 
14
12
  def only(*names)
@@ -26,30 +24,31 @@ module Servactory
26
24
  def method_missing(name, *_args)
27
25
  if name.to_s.end_with?("=")
28
26
  prepared_name = name.to_s.delete("=").to_sym
27
+
29
28
  raise_error_for(:assign, prepared_name)
30
29
  else
31
- raise_error_for(:fetch, name)
30
+ fetch_with(name:) { raise_error_for(:fetch, name) }
32
31
  end
33
32
  end
34
33
 
35
- def respond_to_missing?(*)
36
- false
34
+ def respond_to_missing?(name, *)
35
+ resolve_input(name) || super
37
36
  end
38
37
 
39
38
  private
40
39
 
41
- def define_attribute_methods!
42
- @collection_of_inputs.each do |input|
43
- define_singleton_method(input.internal_name) do
44
- fetch_value(attribute: input)
45
- end
40
+ def fetch_with(name:, &_block)
41
+ predicate = @context.config.predicate_methods_enabled && name.end_with?("?")
46
42
 
47
- next unless @context.config.predicate_methods_enabled
43
+ input_name = predicate ? name.to_s.chomp("?").to_sym : name
48
44
 
49
- define_singleton_method(:"#{input.internal_name}?") do
50
- fetch_predicate(attribute: input)
51
- end
52
- end
45
+ input = @collection_of_inputs.find_by(name: input_name)
46
+
47
+ return yield if input.nil?
48
+
49
+ value = fetch_value(attribute: input)
50
+
51
+ predicate ? Servactory::Utils.query_attribute(value) : value
53
52
  end
54
53
 
55
54
  def fetch_value(attribute:)
@@ -65,8 +64,12 @@ module Servactory
65
64
  value
66
65
  end
67
66
 
68
- def fetch_predicate(attribute:)
69
- Servactory::Utils.query_attribute(fetch_value(attribute:))
67
+ def resolve_input(name)
68
+ return true if @collection_of_inputs.find_by(name:)
69
+
70
+ @context.config.predicate_methods_enabled &&
71
+ name.to_s.end_with?("?") &&
72
+ @collection_of_inputs.find_by(name: name.to_s.chomp("?").to_sym)
70
73
  end
71
74
 
72
75
  def raise_error_for(type, name)
@@ -7,9 +7,6 @@ module Servactory
7
7
  def initialize(context:, collection_of_internals:)
8
8
  @context = context
9
9
  @collection_of_internals = collection_of_internals
10
- @validated_attributes = Set.new
11
-
12
- define_attribute_methods!
13
10
  end
14
11
 
15
12
  def only(*names)
@@ -24,57 +21,61 @@ module Servactory
24
21
  .to_h { |internal| [internal.name, send(internal.name)] }
25
22
  end
26
23
 
27
- def method_missing(name, *_args)
24
+ def method_missing(name, *args)
28
25
  if name.to_s.end_with?("=")
29
26
  prepared_name = name.to_s.delete("=").to_sym
30
- raise_error_for(:assign, prepared_name)
27
+
28
+ assign_with(prepared_name:, value: args.pop) { raise_error_for(:assign, prepared_name) }
31
29
  else
32
- raise_error_for(:fetch, name)
30
+ fetch_with(name:) { raise_error_for(:fetch, name) }
33
31
  end
34
32
  end
35
33
 
36
- def respond_to_missing?(*)
37
- false
34
+ def respond_to_missing?(name, *)
35
+ resolve_internal(name) || super
38
36
  end
39
37
 
40
38
  private
41
39
 
42
- def define_attribute_methods! # rubocop:disable Metrics/MethodLength
43
- @collection_of_internals.each do |internal|
44
- define_singleton_method(internal.name) do
45
- fetch_value(attribute: internal)
46
- end
40
+ def validated_attributes
41
+ @validated_attributes ||= Set.new
42
+ end
47
43
 
48
- define_singleton_method(:"#{internal.name}=") do |value|
49
- assign_value(attribute: internal, value:)
50
- end
44
+ def assign_with(prepared_name:, value:, &_block)
45
+ internal = @collection_of_internals.find_by(name: prepared_name)
51
46
 
52
- next unless @context.config.predicate_methods_enabled
47
+ return yield if internal.nil?
53
48
 
54
- define_singleton_method(:"#{internal.name}?") do
55
- fetch_predicate(attribute: internal)
56
- end
57
- end
58
- end
59
-
60
- def assign_value(attribute:, value:)
61
- @validated_attributes.delete(attribute.name)
49
+ validated_attributes.delete(internal.name)
62
50
 
63
51
  Servactory::Maintenance::Validations::Performer.validate!(
64
52
  context: @context,
65
- attribute:,
53
+ attribute: internal,
66
54
  value:
67
55
  )
68
56
 
69
- @context.send(:servactory_service_warehouse).assign_internal(attribute.name, value)
57
+ @context.send(:servactory_service_warehouse).assign_internal(internal.name, value)
70
58
 
71
- @validated_attributes << attribute.name
59
+ validated_attributes << internal.name
60
+ end
61
+
62
+ def fetch_with(name:, &_block)
63
+ predicate = @context.config.predicate_methods_enabled && name.end_with?("?")
64
+
65
+ internal_name = predicate ? name.to_s.chomp("?").to_sym : name
66
+ internal = @collection_of_internals.find_by(name: internal_name)
67
+
68
+ return yield if internal.nil?
69
+
70
+ internal_value = fetch_value(attribute: internal)
71
+
72
+ predicate ? Servactory::Utils.query_attribute(internal_value) : internal_value
72
73
  end
73
74
 
74
75
  def fetch_value(attribute:)
75
76
  value = @context.send(:servactory_service_warehouse).fetch_internal(attribute.name)
76
77
 
77
- if @validated_attributes.exclude?(attribute.name)
78
+ if validated_attributes.exclude?(attribute.name)
78
79
  Servactory::Maintenance::Validations::Performer.validate!(
79
80
  context: @context,
80
81
  attribute:,
@@ -85,8 +86,12 @@ module Servactory
85
86
  value
86
87
  end
87
88
 
88
- def fetch_predicate(attribute:)
89
- Servactory::Utils.query_attribute(fetch_value(attribute:))
89
+ def resolve_internal(name)
90
+ return true if @collection_of_internals.find_by(name:)
91
+
92
+ @context.config.predicate_methods_enabled &&
93
+ name.to_s.end_with?("?") &&
94
+ @collection_of_internals.find_by(name: name.to_s.chomp("?").to_sym)
90
95
  end
91
96
 
92
97
  def raise_error_for(type, name)
@@ -7,8 +7,6 @@ module Servactory
7
7
  def initialize(context:, collection_of_outputs:)
8
8
  @context = context
9
9
  @collection_of_outputs = collection_of_outputs
10
-
11
- define_attribute_methods!
12
10
  end
13
11
 
14
12
  def only(*names)
@@ -23,55 +21,55 @@ module Servactory
23
21
  .to_h { |output| [output.name, send(output.name)] }
24
22
  end
25
23
 
26
- def method_missing(name, *_args)
24
+ def method_missing(name, *args)
27
25
  if name.to_s.end_with?("=")
28
26
  prepared_name = name.to_s.delete("=").to_sym
29
- raise_error_for(:assign, prepared_name)
27
+
28
+ assign_with(prepared_name:, value: args.pop) { raise_error_for(:assign, prepared_name) }
30
29
  else
31
- raise_error_for(:fetch, name)
30
+ fetch_with(name:) { raise_error_for(:fetch, name) }
32
31
  end
33
32
  end
34
33
 
35
- def respond_to_missing?(*)
36
- false
34
+ def respond_to_missing?(name, *)
35
+ resolve_output(name) || super
37
36
  end
38
37
 
39
38
  private
40
39
 
41
- def define_attribute_methods! # rubocop:disable Metrics/MethodLength
42
- @collection_of_outputs.each do |output|
43
- define_singleton_method(output.name) do
44
- fetch_value(attribute: output)
45
- end
46
-
47
- define_singleton_method(:"#{output.name}=") do |value|
48
- assign_value(attribute: output, value:)
49
- end
40
+ def assign_with(prepared_name:, value:, &_block)
41
+ output = @collection_of_outputs.find_by(name: prepared_name)
50
42
 
51
- next unless @context.config.predicate_methods_enabled
52
-
53
- define_singleton_method(:"#{output.name}?") do
54
- fetch_predicate(attribute: output)
55
- end
56
- end
57
- end
43
+ return yield if output.nil?
58
44
 
59
- def assign_value(attribute:, value:)
60
45
  Servactory::Maintenance::Validations::Performer.validate!(
61
46
  context: @context,
62
- attribute:,
47
+ attribute: output,
63
48
  value:
64
49
  )
65
50
 
66
- @context.send(:servactory_service_warehouse).assign_output(attribute.name, value)
51
+ @context.send(:servactory_service_warehouse).assign_output(output.name, value)
67
52
  end
68
53
 
69
- def fetch_value(attribute:)
70
- @context.send(:servactory_service_warehouse).fetch_output(attribute.name)
54
+ def fetch_with(name:, &_block)
55
+ predicate = @context.config.predicate_methods_enabled && name.end_with?("?")
56
+
57
+ output_name = predicate ? name.to_s.chomp("?").to_sym : name
58
+ output = @collection_of_outputs.find_by(name: output_name)
59
+
60
+ return yield if output.nil?
61
+
62
+ output_value = @context.send(:servactory_service_warehouse).fetch_output(output.name)
63
+
64
+ predicate ? Servactory::Utils.query_attribute(output_value) : output_value
71
65
  end
72
66
 
73
- def fetch_predicate(attribute:)
74
- Servactory::Utils.query_attribute(fetch_value(attribute:))
67
+ def resolve_output(name)
68
+ return true if @collection_of_outputs.find_by(name:)
69
+
70
+ @context.config.predicate_methods_enabled &&
71
+ name.to_s.end_with?("?") &&
72
+ @collection_of_outputs.find_by(name: name.to_s.chomp("?").to_sym)
75
73
  end
76
74
 
77
75
  def raise_error_for(type, name)
@@ -41,7 +41,7 @@ module Servactory
41
41
  # ```ruby
42
42
  # result.active? # Equivalent to Utils.query_attribute(result.active)
43
43
  # ```
44
- class Result # rubocop:disable Metrics/ClassLength
44
+ class Result
45
45
  # Internal container for service output values.
46
46
  #
47
47
  # Provides dynamic method access to output values.
@@ -55,8 +55,6 @@ module Servactory
55
55
  def initialize(outputs:, predicate_methods_enabled:)
56
56
  @outputs = outputs
57
57
  @predicate_methods_enabled = predicate_methods_enabled
58
-
59
- define_attribute_methods!
60
58
  end
61
59
 
62
60
  # Returns string representation for debugging.
@@ -66,26 +64,34 @@ module Servactory
66
64
  "#<#{self.class.name} #{draw_result}>"
67
65
  end
68
66
 
69
- private
70
-
71
- # Defines singleton accessor methods for output values on this instance.
72
- #
73
- # Creates getter methods for each output key and, when predicate methods
74
- # are enabled, predicate methods (e.g., user?) for boolean queries.
75
- #
76
- # @return [void]
77
- def define_attribute_methods!
78
- @outputs.each_key do |name|
79
- define_singleton_method(name) { @outputs[name] }
67
+ # Delegates method calls to stored outputs.
68
+ def method_missing(name, *args)
69
+ if name.to_s.end_with?("?")
70
+ base_name = name.to_s.chomp("?").to_sym
71
+ if @predicate_methods_enabled && @outputs.key?(base_name)
72
+ return Servactory::Utils.query_attribute(@outputs[base_name])
73
+ end
74
+ elsif @outputs.key?(name)
75
+ return @outputs[name]
76
+ end
80
77
 
81
- next unless @predicate_methods_enabled
78
+ super
79
+ end
82
80
 
83
- define_singleton_method(:"#{name}?") do
84
- Servactory::Utils.query_attribute(@outputs[name])
85
- end
81
+ # Checks if method corresponds to stored output.
82
+ def respond_to_missing?(name, include_private = false)
83
+ if name.to_s.end_with?("?")
84
+ base_name = name.to_s.chomp("?").to_sym
85
+ return true if @predicate_methods_enabled && @outputs.key?(base_name)
86
+ elsif @outputs.key?(name)
87
+ return true
86
88
  end
89
+
90
+ super
87
91
  end
88
92
 
93
+ private
94
+
89
95
  # Returns array of output attribute names.
90
96
  #
91
97
  # @return [Array<Symbol>] Output names without predicates
@@ -282,9 +288,6 @@ module Servactory
282
288
 
283
289
  # Delegates method calls to the outputs container.
284
290
  #
285
- # On first access, triggers lazy initialization of outputs and
286
- # installs singleton delegator methods for subsequent direct access.
287
- #
288
291
  # @param name [Symbol] Method name (output attribute)
289
292
  # @param args [Array] Method arguments
290
293
  # @param block [Proc] Optional block
@@ -332,12 +335,9 @@ module Servactory
332
335
 
333
336
  # Returns outputs container, lazily initialized.
334
337
  #
335
- # On first access, also defines singleton delegator methods on this
336
- # Result instance for subsequent direct access.
337
- #
338
338
  # @return [Outputs] Outputs container with service values
339
339
  def outputs
340
- @outputs ||= build_outputs.tap { |outputs_container| define_output_delegators!(outputs_container) }
340
+ @outputs ||= build_outputs
341
341
  end
342
342
 
343
343
  # Builds Outputs container with predicate configuration.
@@ -362,21 +362,6 @@ module Servactory
362
362
  hash
363
363
  end
364
364
 
365
- # Defines singleton delegator methods on this Result instance
366
- # for direct access to output values without method_missing.
367
- #
368
- # @param outputs_container [Outputs] Outputs container to delegate to
369
- # @return [void]
370
- def define_output_delegators!(outputs_container)
371
- outputs_container.send(:output_names).each do |name|
372
- define_singleton_method(name) { outputs.public_send(name) }
373
- end
374
-
375
- outputs_container.send(:predicate_names).each do |name|
376
- define_singleton_method(name) { outputs.public_send(name) }
377
- end
378
- end
379
-
380
365
  ########################################################################
381
366
 
382
367
  # Wraps NoMethodError with contextual failure.
@@ -5,7 +5,7 @@ module Servactory
5
5
  MAJOR = 3
6
6
  MINOR = 1
7
7
  PATCH = 0
8
- PRE = "rc1"
8
+ PRE = "rc2"
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.1.0.rc1
4
+ version: 3.1.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton Sokolov