defi 3.0.0 → 3.0.1

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: bd965274ab9b7a6dd1303d7aa7b4c1da9c87551c6197a5075ea1f6a8c409df52
4
- data.tar.gz: 2fc6a867f949feeb94e971347313fd1b734c5851bb1f770e77bc6b2c0d72e9d8
3
+ metadata.gz: cbd2a5befa5ac9808bfe1c121549311dfed58c0a48070b9708ec46621a101255
4
+ data.tar.gz: b1f16e2e70d07e377e7f662a807afb1afbe9cc971535cb683d5000b19b0306de
5
5
  SHA512:
6
- metadata.gz: 99d0012c6768b9e38db3a149cb9021c3fdad056705748079e8e33ca6b7e05f55ec551ea1b784eb2cfba31dd3bae2f5454d75eeb8469fa5372321c192c42dcf99
7
- data.tar.gz: 789d8cd29d0cb8d608980c88b995d5d188e93febf868715113a1b274fe35cb54f2cd01f5b7a0f57d3e5ba804099c3129ab824e7ecfc0b50cf6b903df926bd935
6
+ metadata.gz: a673ab6344aa7f6ebe0b04ff7556b0f3d5524cec97f26810613858afe874f96362081a293cabadcdcf8a09da1c10c75ef8fa0e5a3efc39fc3f075660febc6a9a
7
+ data.tar.gz: a8c78c9725743ba1efeb8e3ac12afb5dca6403d8a7d6b714142814db42d7d60b075b5a3d5431a2145b33319f2c6d08742e50fe91d4e7ea5916579a8185b4bcdd
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015-2024 Cyril Kato
3
+ Copyright (c) 2015-2025 Cyril Kato
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  [![Version](https://img.shields.io/github/v/tag/fixrb/defi?label=Version&logo=github)](https://github.com/fixrb/defi/tags)
4
4
  [![Yard documentation](https://img.shields.io/badge/Yard-documentation-blue.svg?logo=github)](https://rubydoc.info/github/fixrb/defi/main)
5
- [![Ruby](https://github.com/fixrb/defi/workflows/Ruby/badge.svg?branch=main)](https://github.com/fixrb/defi/actions?query=workflow%3Aruby+branch%3Amain)
6
- [![RuboCop](https://github.com/fixrb/defi/workflows/RuboCop/badge.svg?branch=main)](https://github.com/fixrb/defi/actions?query=workflow%3Arubocop+branch%3Amain)
7
5
  [![License](https://img.shields.io/github/license/fixrb/defi?label=License&logo=github)](https://github.com/fixrb/defi/raw/main/LICENSE.md)
8
6
 
9
7
  **Defi** is a streamlined Ruby library designed for the specification of method arguments while respecting their signatures.
@@ -83,11 +81,6 @@ __Defi__ follows [Semantic Versioning 2.0](https://semver.org/).
83
81
 
84
82
  The [gem](https://rubygems.org/gems/defi) is available as open source under the terms of the [MIT License](https://github.com/fixrb/defi/raw/main/LICENSE.md).
85
83
 
86
- ---
84
+ ## Sponsors
87
85
 
88
- <p>
89
- This project is sponsored by:<br />
90
- <a href="https://sashite.com/"><img
91
- src="https://github.com/fixrb/defi/raw/main/img/sashite.png"
92
- alt="Sashité" /></a>
93
- </p>
86
+ This project is sponsored by [Sashité](https://sashite.com/)
data/lib/defi/method.rb CHANGED
@@ -2,18 +2,19 @@
2
2
 
3
3
  module Defi
4
4
  # Represents a method to be applied against an object.
5
- # This class encapsulates the method name, its arguments, keyword arguments,
6
- # and an optional block, enabling dynamic method invocation.
5
+ # Encapsulates method name, arguments, keyword arguments and blocks
6
+ # for dynamic method invocation with proper error handling.
7
7
  class Method < ::BasicObject
8
8
  # Initialize a new Method object.
9
9
  #
10
- # @param name [Symbol] The name of the method.
11
- # @param args [Array] Any arguments of the method.
12
- # @param opts [Hash] Any keyword arguments of the method.
13
- # @param block [Proc] Any block argument of the method.
14
- # @raise [ArgumentError] If the name is not a symbol.
10
+ # @param name [Symbol] The method name
11
+ # @param args [Array] Positional arguments
12
+ # @param opts [Hash] Keyword arguments
13
+ # @param block [Proc] Optional block
14
+ #
15
+ # @raise [ArgumentError] If name is not a Symbol, raises with the actual class received
15
16
  def initialize(name, *args, **opts, &block)
16
- raise ::ArgumentError, name.class.inspect unless name.is_a?(::Symbol)
17
+ raise ::ArgumentError, "Method name must be a Symbol, got: #{name.class}" unless name.is_a?(::Symbol)
17
18
 
18
19
  @name = name
19
20
  @args = args
@@ -23,19 +24,23 @@ module Defi
23
24
 
24
25
  # Applies the method to the given object.
25
26
  #
26
- # @example
27
- # add = Defi::Method.new(:+, 1)
28
- # add.to(2).call # => 3
27
+ # @param object [#object_id] Target object for method invocation
28
+ # @return [Defi::Value] Result wrapper containing return value or exception
29
+ #
30
+ # @example Basic arithmetic
31
+ # Defi::Method.new(:+, 1).to(2).call # => 3
29
32
  #
30
- # @param object [#object_id] The object to method.
31
- # @return [Defi::Value] The actual value, to raise or to return.
33
+ # @example Block usage
34
+ # Defi::Method.new(:map) { |x| x * 2 }.to([1, 2, 3]).call # => [2, 4, 6]
35
+ #
36
+ # @example Error handling
37
+ # result = Defi::Method.new(:undefined).to(42)
38
+ # result.raised? # => true
32
39
  def to(object)
33
40
  Value.new { object.public_send(@name, *@args, **@opts, &@block) }
34
41
  end
35
42
 
36
- # Returns a hash containing the method's properties.
37
- #
38
- # @return [Hash] The properties of the method.
43
+ # @return [Hash] Method properties
39
44
  def to_h
40
45
  {
41
46
  name: @name,
@@ -45,53 +50,54 @@ module Defi
45
50
  }
46
51
  end
47
52
 
48
- # rubocop:disable Metrics/AbcSize
49
- # rubocop:disable Metrics/CyclomaticComplexity
50
-
51
- # Returns a string representation of the method.
53
+ # @return [String] Human-readable representation
52
54
  #
53
55
  # @example
54
- # add = Defi::Method.new(:+, 1)
55
- # add.to_s # => ".+(1)"
56
+ # Defi::Method.new(:+, 1).inspect
57
+ # # => "Defi(name: :+, args: [1], opts: {}, block: nil)"
58
+ def inspect
59
+ "Defi(" \
60
+ "name: #{@name.inspect}, " \
61
+ "args: #{@args.inspect}, " \
62
+ "opts: #{@opts.inspect}, " \
63
+ "block: #{@block.nil? ? "nil" : "<Proc>"})"
64
+ end
65
+
66
+ # @return [String] String representation of the method call
56
67
  #
57
- # @return [String] The string representation of the method.
68
+ # @example
69
+ # Defi::Method.new(:+, 1).to_s # => ".+(1)"
70
+ # Defi::Method.new(:map) { |x| x }.to_s # => ".map(<Proc>)"
58
71
  def to_s
59
- string = ".#{@name}"
60
- return string if @args.empty? && @opts.empty? && @block.nil?
72
+ return ".#{@name}" if no_arguments?
61
73
 
62
- stringified_args = @args.inspect[1..-2]
63
- stringified_opts = @opts.inspect[1..-2]
64
- stringified_block = "<Proc>" unless @block.nil?
74
+ ".#{@name}(#{stringified_arguments})"
75
+ end
65
76
 
66
- stringified_items = []
67
- stringified_items << stringified_args unless @args.empty?
68
- stringified_items << stringified_opts unless @opts.empty?
69
- stringified_items << stringified_block unless @block.nil?
77
+ private
70
78
 
71
- "#{string}(#{stringified_items.join(", ")})"
79
+ def no_arguments?
80
+ @args.empty? && @opts.empty? && @block.nil?
72
81
  end
73
82
 
74
- # rubocop:enable Metrics/AbcSize
75
- # rubocop:enable Metrics/CyclomaticComplexity
83
+ def stringified_arguments
84
+ [
85
+ args_string,
86
+ opts_string,
87
+ block_string
88
+ ].compact.join(", ")
89
+ end
76
90
 
77
- # Returns a human-readable representation of the method.
78
- #
79
- # @example
80
- # add = Defi::Method.new(:+, 1)
81
- # add.inspect # => "Defi(name: :+, args: [1], opts: {}, block: nil)"
82
- #
83
- # @return [String] The human-readable representation of the method.
84
- def inspect
85
- inspected_name = @name.inspect
86
- inspected_args = @args.inspect
87
- inspected_opts = @opts.inspect
88
- inspected_block = @block.nil? ? "nil" : "<Proc>"
91
+ def args_string
92
+ @args.inspect[1..-2] unless @args.empty?
93
+ end
89
94
 
90
- "Defi(" \
91
- "name: #{inspected_name}, " \
92
- "args: #{inspected_args}, " \
93
- "opts: #{inspected_opts}, " \
94
- "block: #{inspected_block})"
95
+ def opts_string
96
+ @opts.inspect[1..-2] unless @opts.empty?
97
+ end
98
+
99
+ def block_string
100
+ "<Proc>" if @block
95
101
  end
96
102
  end
97
103
  end
data/lib/defi/value.rb CHANGED
@@ -1,93 +1,83 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Defi
4
- # Represents a result of an operation, encapsulating either the returned value
5
- # or an exception raised during the execution.
6
- #
7
- # This class is used to handle the outcome of a method invocation, allowing
8
- # to distinguish between successful results and exceptions.
4
+ # Represents a result of an operation, encapsulating both successful returns
5
+ # and exceptions. This class intentionally catches all exceptions (Exception)
6
+ # instead of StandardError to maintain complete control over method execution
7
+ # outcomes, particularly in testing contexts. This ensures that system-level
8
+ # exceptions like SystemExit cannot prematurely terminate test execution with
9
+ # potentially false positive results.
9
10
  class Value
10
11
  RAISE = "raise"
11
12
  RETURN = "return"
12
13
 
13
- # @return [#object_id] The returned or the raised object.
14
+ # @return [#object_id] The returned value or caught exception
14
15
  attr_reader :object
15
16
 
16
- # Initializes a Value object with the result of the provided block.
17
- # Captures any exception raised during the block execution.
17
+ # Initializes a Value object by executing the provided block.
18
18
  #
19
- # @example
19
+ # @example Successful execution
20
20
  # value = Defi::Value.new { 1 + 1 }
21
21
  # value.call # => 2
22
+ # value.raised? # => false
22
23
  #
23
- # @example Handling an exception
24
- # value = Defi::Value.new { raise 'Error' }
25
- # value.call # raises 'Error'
24
+ # @example Exception handling
25
+ # value = Defi::Value.new { raise TypeError, "Invalid type" }
26
+ # value.raised? # => true
27
+ # value.object # => #<TypeError: Invalid type>
28
+ #
29
+ # @note This implementation catches Exception instead of StandardError
30
+ # to provide complete control over method execution outcomes,
31
+ # including system-level exceptions when needed.
26
32
  #
27
- # @yieldreturn [#object_id] The result of the block or the exception raised.
28
- # rubocop:disable Lint/RescueException
33
+ # @yieldreturn [#object_id] Result or exception from block execution
29
34
  def initialize
30
35
  @object = yield
31
36
  @raised = false
32
- rescue ::Exception => e
37
+ rescue ::Exception => e # rubocop:disable Lint/RescueException
33
38
  @object = e
34
39
  @raised = true
35
40
  end
36
- # rubocop:enable Lint/RescueException
37
41
 
38
- # Returns the object if no exception was raised, otherwise raises the exception.
42
+ # Returns the result or raises the captured exception.
43
+ #
44
+ # @example With successful result
45
+ # Value.new { "success" }.call # => "success"
39
46
  #
40
- # @example
41
- # value = Defi::Value.new { "Hello" }
42
- # value.call # => "Hello"
47
+ # @example With exception
48
+ # Value.new { raise "error" }.call # raises RuntimeError: error
43
49
  #
44
- # @return [#object_id] The returned object or raises the captured exception.
50
+ # @return [#object_id] The operation result
51
+ # @raise [Exception] The captured exception if raised? is true
45
52
  def call
46
53
  raise object if raised?
47
54
 
48
55
  object
49
56
  end
50
57
 
51
- # Checks if an exception was raised during the execution.
52
- #
53
- # @example
54
- # value = Defi::Value.new { raise 'Error' }
55
- # value.raised? # => true
56
- #
57
- # @return [Boolean] True if an exception was raised, otherwise false.
58
+ # @return [Boolean] true if execution raised an exception
58
59
  def raised?
59
60
  @raised
60
61
  end
61
62
 
62
- # Returns a hash containing the properties of the Value object.
63
- #
64
- # @return [Hash] The properties of the Value object.
63
+ # @return [String] Human-readable representation
64
+ def inspect
65
+ "Value(object: #{object}, raised: #{raised?})"
66
+ end
67
+
68
+ # @return [Hash] Value properties
65
69
  def to_h
66
- {
67
- raised: raised?,
68
- object:
69
- }
70
+ { raised: raised?, object: }
70
71
  end
71
72
 
72
- # Returns a string representation of the Value object.
73
- #
74
- # @return [String] The string representation of the Value object.
73
+ # @return [String] String representation showing outcome type and value
75
74
  def to_s
76
75
  "#{raise_or_return} #{object}"
77
76
  end
78
77
 
79
- # Returns a human-readable representation of the Value object.
80
- #
81
- # @return [String] The human-readable representation of the Value object.
82
- def inspect
83
- "Value(object: #{object}, raised: #{raised?})"
84
- end
85
-
86
78
  private
87
79
 
88
- # Returns a string indicating whether the object was raised or returned.
89
- #
90
- # @return [String] A "raise" or "return" string.
80
+ # @return [String] Execution outcome type
91
81
  def raise_or_return
92
82
  raised? ? RAISE : RETURN
93
83
  end
data/lib/defi.rb CHANGED
@@ -2,27 +2,33 @@
2
2
 
3
3
  # Namespace for the Defi library.
4
4
  #
5
- # This file serves as the entry point for the Defi library, establishing the
6
- # Defi namespace and requiring necessary components. It is typically required
7
- # at the beginning of using the Defi library in an application.
5
+ # Defi provides a flexible way to specify method calls with arguments
6
+ # for later execution. It supports method chaining, exception handling,
7
+ # and value inspection.
8
8
  #
9
- # @example Requiring the Defi library in a Ruby application
10
- # require "defi"
11
- #
12
- # @example Adding 2 to 1
13
- # # Create a Defi method object for addition with an argument of 2
9
+ # @example Basic arithmetic operation
14
10
  # addition = Defi(:+, 2)
15
- # addition.inspect # => "Defi(name: :+, args: [2], opts: {}, block: nil)"
11
+ # addition.to(1).call # => 3
12
+ #
13
+ # @example String manipulation
14
+ # upcase = Defi(:upcase)
15
+ # upcase.to("hello").call # => "HELLO"
16
+ #
17
+ # @example Method with keyword arguments
18
+ # format = Defi(:format, precision: 2)
19
+ # format.to(3.14159).call # => "3.14"
16
20
  #
17
- # # Apply the addition to the number 1
18
- # result = addition.to(1)
19
- # result # => Value(object: 3, raised: false)
21
+ # @example Block usage
22
+ # map_double = Defi(:map) { |x| x * 2 }
23
+ # map_double.to([1, 2, 3]).call # => [2, 4, 6]
20
24
  #
21
- # # Execute the addition and get the result
22
- # result.call # => 3
25
+ # @example Error handling
26
+ # result = Defi(:undefined_method).to(42)
27
+ # result.raised? # => true
28
+ # result.object # => #<NoMethodError: ...>
23
29
  #
24
30
  module Defi
25
31
  end
26
32
 
27
- # Require additional components of the Defi library.
33
+ # Load core components
28
34
  require_relative "kernel"
data/lib/kernel.rb CHANGED
@@ -2,41 +2,44 @@
2
2
 
3
3
  require_relative File.join("defi", "method")
4
4
 
5
- # Extension of the Kernel module to include the Defi method.
6
- # The Defi method is a convenient way to create Method objects
7
- # that encapsulate a method name and its arguments, offering a
8
- # dynamic approach to method invocation.
5
+ # Core Ruby module extended to provide the Defi method globally.
6
+ # This extension allows for convenient method encapsulation and
7
+ # delayed execution through the Defi method, accessible anywhere
8
+ # in the Ruby environment.
9
9
  module Kernel
10
- # Disabling the RuboCop rule for method naming conventions
11
- # to define a method with an uppercase name for stylistic reasons.
12
10
  # rubocop:disable Naming/MethodName
13
11
 
14
12
  # Creates a new Defi::Method instance.
15
- # This method provides a simple and elegant way to encapsulate
16
- # a method name and its arguments for later invocation.
13
+ # This method provides a flexible way to encapsulate a method name along with its
14
+ # arguments, keyword arguments, and an optional block for later invocation.
17
15
  #
18
- # @example Creating a Defi method without arguments
19
- # Defi(:foo).inspect # => "Defi(name: :foo, args: [], opts: {}, block: nil)"
16
+ # @param method_name [Symbol] The method name to be sent to an object
17
+ # @param args [Array] Positional arguments to be passed to the method
18
+ # @param opts [Hash] Keyword arguments to be passed to the method
19
+ # @param block [Proc] Optional block to be passed to the method
20
20
  #
21
- # @example Adding 2 to 1
22
- # # Create a Defi method object for addition with an argument of 2
23
- # addition = Defi(:+, 2)
24
- # addition.inspect # => "Defi(name: :+, args: [2], opts: {}, block: nil)"
21
+ # @example Basic method without arguments
22
+ # Defi(:to_s)
25
23
  #
26
- # # Apply the addition to the number 1
27
- # result = addition.to(1)
28
- # result # => Value(object: 3, raised: false)
24
+ # @example Method with positional arguments
25
+ # Defi(:+, 2)
26
+ # Defi(:[], 0, 2) # For array/string slicing
29
27
  #
30
- # # Execute the addition and get the result
31
- # result.call # => 3
28
+ # @example Method with keyword arguments
29
+ # Defi(:transform, x: 1, y: 2)
32
30
  #
33
- # @param method_name [Symbol] The method name to be sent to an object.
31
+ # @example Method with a block
32
+ # Defi(:map) { |x| x * 2 }
34
33
  #
35
- # @return [Defi::Method] An instance of Defi::Method encapsulating the method name and provided arguments.
36
- def Defi(method_name, ...)
37
- ::Defi::Method.new(method_name, ...)
34
+ # @example Complex method call
35
+ # Defi(:reduce, 0, &:+) # Sum an array
36
+ #
37
+ # @raise [ArgumentError] If method_name is not a Symbol
38
+ #
39
+ # @return [Defi::Method] An instance of Defi::Method encapsulating the method call
40
+ def Defi(method_name, *args, **opts, &block)
41
+ ::Defi::Method.new(method_name, *args, **opts, &block)
38
42
  end
39
43
 
40
- # Re-enabling the RuboCop rule for method naming conventions.
41
44
  # rubocop:enable Naming/MethodName
42
45
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: defi
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Kato
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-25 00:00:00.000000000 Z
11
+ date: 2024-12-31 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Challenge library.
14
14
  email: contact@cyril.email
@@ -27,7 +27,7 @@ licenses:
27
27
  - MIT
28
28
  metadata:
29
29
  rubygems_mfa_required: 'true'
30
- post_install_message:
30
+ post_install_message:
31
31
  rdoc_options: []
32
32
  require_paths:
33
33
  - lib
@@ -35,15 +35,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
35
35
  requirements:
36
36
  - - ">="
37
37
  - !ruby/object:Gem::Version
38
- version: 3.2.0
38
+ version: 3.1.0
39
39
  required_rubygems_version: !ruby/object:Gem::Requirement
40
40
  requirements:
41
41
  - - ">="
42
42
  - !ruby/object:Gem::Version
43
43
  version: '0'
44
44
  requirements: []
45
- rubygems_version: 3.4.19
46
- signing_key:
45
+ rubygems_version: 3.3.27
46
+ signing_key:
47
47
  specification_version: 4
48
48
  summary: Challenge library.
49
49
  test_files: []