lib/defi/method.rb in defi-3.0.0 vs lib/defi/method.rb in defi-3.0.1
- old
+ new
@@ -1,98 +1,104 @@
# frozen_string_literal: true
module Defi
# Represents a method to be applied against an object.
- # This class encapsulates the method name, its arguments, keyword arguments,
- # and an optional block, enabling dynamic method invocation.
+ # Encapsulates method name, arguments, keyword arguments and blocks
+ # for dynamic method invocation with proper error handling.
class Method < ::BasicObject
# Initialize a new Method object.
#
- # @param name [Symbol] The name of the method.
- # @param args [Array] Any arguments of the method.
- # @param opts [Hash] Any keyword arguments of the method.
- # @param block [Proc] Any block argument of the method.
- # @raise [ArgumentError] If the name is not a symbol.
+ # @param name [Symbol] The method name
+ # @param args [Array] Positional arguments
+ # @param opts [Hash] Keyword arguments
+ # @param block [Proc] Optional block
+ #
+ # @raise [ArgumentError] If name is not a Symbol, raises with the actual class received
def initialize(name, *args, **opts, &block)
- raise ::ArgumentError, name.class.inspect unless name.is_a?(::Symbol)
+ raise ::ArgumentError, "Method name must be a Symbol, got: #{name.class}" unless name.is_a?(::Symbol)
@name = name
@args = args
@opts = opts
@block = block
end
# Applies the method to the given object.
#
- # @example
- # add = Defi::Method.new(:+, 1)
- # add.to(2).call # => 3
+ # @param object [#object_id] Target object for method invocation
+ # @return [Defi::Value] Result wrapper containing return value or exception
#
- # @param object [#object_id] The object to method.
- # @return [Defi::Value] The actual value, to raise or to return.
+ # @example Basic arithmetic
+ # Defi::Method.new(:+, 1).to(2).call # => 3
+ #
+ # @example Block usage
+ # Defi::Method.new(:map) { |x| x * 2 }.to([1, 2, 3]).call # => [2, 4, 6]
+ #
+ # @example Error handling
+ # result = Defi::Method.new(:undefined).to(42)
+ # result.raised? # => true
def to(object)
Value.new { object.public_send(@name, *@args, **@opts, &@block) }
end
- # Returns a hash containing the method's properties.
- #
- # @return [Hash] The properties of the method.
+ # @return [Hash] Method properties
def to_h
{
name: @name,
args: @args,
opts: @opts,
block: @block
}
end
- # rubocop:disable Metrics/AbcSize
- # rubocop:disable Metrics/CyclomaticComplexity
-
- # Returns a string representation of the method.
+ # @return [String] Human-readable representation
#
# @example
- # add = Defi::Method.new(:+, 1)
- # add.to_s # => ".+(1)"
+ # Defi::Method.new(:+, 1).inspect
+ # # => "Defi(name: :+, args: [1], opts: {}, block: nil)"
+ def inspect
+ "Defi(" \
+ "name: #{@name.inspect}, " \
+ "args: #{@args.inspect}, " \
+ "opts: #{@opts.inspect}, " \
+ "block: #{@block.nil? ? "nil" : "<Proc>"})"
+ end
+
+ # @return [String] String representation of the method call
#
- # @return [String] The string representation of the method.
+ # @example
+ # Defi::Method.new(:+, 1).to_s # => ".+(1)"
+ # Defi::Method.new(:map) { |x| x }.to_s # => ".map(<Proc>)"
def to_s
- string = ".#{@name}"
- return string if @args.empty? && @opts.empty? && @block.nil?
+ return ".#{@name}" if no_arguments?
- stringified_args = @args.inspect[1..-2]
- stringified_opts = @opts.inspect[1..-2]
- stringified_block = "<Proc>" unless @block.nil?
+ ".#{@name}(#{stringified_arguments})"
+ end
- stringified_items = []
- stringified_items << stringified_args unless @args.empty?
- stringified_items << stringified_opts unless @opts.empty?
- stringified_items << stringified_block unless @block.nil?
+ private
- "#{string}(#{stringified_items.join(", ")})"
+ def no_arguments?
+ @args.empty? && @opts.empty? && @block.nil?
end
- # rubocop:enable Metrics/AbcSize
- # rubocop:enable Metrics/CyclomaticComplexity
+ def stringified_arguments
+ [
+ args_string,
+ opts_string,
+ block_string
+ ].compact.join(", ")
+ end
- # Returns a human-readable representation of the method.
- #
- # @example
- # add = Defi::Method.new(:+, 1)
- # add.inspect # => "Defi(name: :+, args: [1], opts: {}, block: nil)"
- #
- # @return [String] The human-readable representation of the method.
- def inspect
- inspected_name = @name.inspect
- inspected_args = @args.inspect
- inspected_opts = @opts.inspect
- inspected_block = @block.nil? ? "nil" : "<Proc>"
+ def args_string
+ @args.inspect[1..-2] unless @args.empty?
+ end
- "Defi(" \
- "name: #{inspected_name}, " \
- "args: #{inspected_args}, " \
- "opts: #{inspected_opts}, " \
- "block: #{inspected_block})"
+ def opts_string
+ @opts.inspect[1..-2] unless @opts.empty?
+ end
+
+ def block_string
+ "<Proc>" if @block
end
end
end
require_relative "value"