Module: Toolx::Core::Operation::SimplifiedResult

Included in:
Toolx::Core::Operation
Defined in:
lib/toolx/core/operation/simplified_result.rb

Instance Method Summary collapse

Instance Method Details

#simplified_result(attr_name) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/toolx/core/operation/simplified_result.rb', line 4

def simplified_result(attr_name)
  # This module allows defining a simplified accessor for the result of an Operation.
  # When included and `simplified_result :attribute_name` is called,
  # it adds a class-level `[]` and `.()` method that initializes the operation,
  # performs it, and returns the specified attribute from the result.
  #
  # Example:
  #
  #   class Country::Name < Operation
  #     simplified_result :value
  #     # ...
  #   end
  #
  #   Country::Name[source: "PL"] # => returns the value attribute from the result
  #   or
  #   Country::Name.call(source: "PL") # => same as above
  #   Country::Name.(source: "PL") # => same as above
  #
  # This is useful for operations that return a single value
  # and should provide a concise and readable API.
  define_singleton_method(:[]) do |*args_array, **kwargs|
    # new(**args).perform.public_send(attr_name)
   begin
      if args_array.empty?
        # Regular keyword arguments: Code[source: 'PL']
        new(**kwargs).perform.public_send(attr_name)
      else
        # Handle single argument like Code[:OK]
        arg = args_array.first

        if arg.is_a?(Hash)
          # Hash argument: Code[{source: 'PL'}]
          new(**arg).perform.public_send(attr_name)
        else
          # Non-hash argument like Symbol: Code[:OK]
          # Try to convert to {source: :OK} format
          if const_defined?(:Params, false) && (first_param = const_get(:Params, false).schema.keys.first)
            new(**{first_param => arg}).perform.public_send(attr_name)
          else
            raise TypeError, "Cannot convert #{arg.class} to parameters hash"
          end
        end
      end
    rescue TypeError, ArgumentError => e
      required = if const_defined?(:Params, false)
        const_get(:Params, false).schema.keys.join(', ')
      else
        'Operation params are wrongly assigned or not defined'
      end

      message = <<~MSG
        Expected #{self.name} keyword args: #{required}
        Got: #{(args_array.first || kwargs).inspect}
        Message: #{e.message}
      MSG

      raise Toolx::Core::Operation::ParamsWrapper::ParamsArgumentError.new(message, e)
    end
    # begin
    #   new(**args).perform.public_send(attr_name)
    # rescue TypeError, ArgumentError => e
    #   required = if const_defined?(:Params, false)
    #     const_get(:Params, false).schema.keys.join(', ')
    #   else
    #     'Operation params are wrongly assigned or not defined'
    #   end
    #
    #   raise ArgumentError, <<~MSG
    #     Expected #{self.name} keyword args: #{required}
    #     Got: #{args.inspect}
    #     #{e.message}
    #   MSG
    # end
  end

  class << self
    alias_method :call, :[]
  end
end