defi 2.0.7 → 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: 45f62cb331ea97335ed07945d26c22a25f3ee7c826ded161d1432018e2e1005c
4
- data.tar.gz: 1067904cd927baeb4c4f5bb8a52260ff813b66f1987e774baaf5916dd10922fa
3
+ metadata.gz: cbd2a5befa5ac9808bfe1c121549311dfed58c0a48070b9708ec46621a101255
4
+ data.tar.gz: b1f16e2e70d07e377e7f662a807afb1afbe9cc971535cb683d5000b19b0306de
5
5
  SHA512:
6
- metadata.gz: 7fbd50efbc1db138975db94ab8c5b876b203443719d780032ac97a2e9129366b85dec847fc8cff0655b3046b02b423f8f2717c8c36b6c11fe45ba03772fc674e
7
- data.tar.gz: a6ee3bb73c8dbbca088d2df08239f31c3451b0bee4075d4f6499d1d45625daab3314ce954fcde3b354d3a564bcbee3557201f74fa7fce65640776ada36e9a214
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-2022 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
@@ -1,12 +1,18 @@
1
1
  # Defi
2
2
 
3
- [![Version](https://img.shields.io/github/v/tag/fixrb/defi?label=Version&logo=github)](https://github.com/fixrb/defi/releases)
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
- [![CI](https://github.com/fixrb/defi/workflows/CI/badge.svg?branch=main)](https://github.com/fixrb/defi/actions?query=workflow%3Aci+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
- > Challenge library.
7
+ **Defi** is a streamlined Ruby library designed for the specification of method arguments while respecting their signatures.
8
+ Rather than representing method signatures themselves, Defi focuses on providing a way to furnish methods with appropriate arguments, thereby preparing them for invocation.
9
+
10
+ This approach serves as an alternative to traditional methods like `Object#method` and `UnboundMethod`.
11
+ Where `Object#method` is bound to a specific object and `UnboundMethod` requires compatibility with the method’s originating class, Defi offers a more flexible and universal way to prepare method calls.
12
+ It allows method arguments to be specified in advance and then applied to any compatible object – those equipped with corresponding methods.
13
+
14
+ Defi is particularly useful in scenarios where you need to apply a set of method arguments across different objects to observe the varying outcomes, whether they be returned values or exceptions.
15
+ This makes it an ideal tool for testing, method comparison across different implementations, or any situation where method behavior needs to be assessed dynamically across various objects.
10
16
 
11
17
  ## Installation
12
18
 
@@ -30,26 +36,39 @@ gem install defi
30
36
 
31
37
  ## Usage
32
38
 
33
- Let's multiply by `7` the number `6`:
39
+ The `Defi` library simplifies the task of applying method signatures to various objects, regardless of their type (instances, modules, etc.).
40
+ Below are some detailed examples to demonstrate its versatility and ease of use:
34
41
 
35
- ```ruby
36
- Defi.send(:*, 7).to(6).call # => 42
37
- ```
42
+ ### Example 1: Multiplying Numbers
38
43
 
39
- Now, let's challenge "`foo`" with `boom` method:
44
+ Suppose you want to multiply the number `6` by `7`.
45
+ With `Defi`, this can be elegantly done as follows:
40
46
 
41
47
  ```ruby
42
- Defi.send(:boom).to("foo").call # NoMethodError: undefined method `boom' for "foo":String
48
+ result = Defi(:*, 7).to(6).call
49
+ puts result # Output: 42
43
50
  ```
44
51
 
45
- Let's challenge "`hello world`" with `gsub!` in isolation:
52
+ Here, `Defi(:*, 7)` creates a challenge with the multiplication method (`:*`) and the argument `7`.
53
+ The `.to(6)` method specifies that this challenge should be applied to the number `6`.
54
+ Finally, `.call` executes the challenge, yielding the result `42`.
55
+
56
+ ### Example 2: Invoking an Undefined Method
57
+
58
+ `Defi` also elegantly handles cases where the method might not exist on the target object.
59
+ For instance:
46
60
 
47
61
  ```ruby
48
- some_text = "hello world"
49
- Defi.send(:gsub!, "world", "Alice").to!(some_text).call # => "hello Alice"
50
- some_text # => "hello world"
62
+ begin
63
+ Defi(:boom).to("foo").call
64
+ rescue NoMethodError => e
65
+ puts e.message # Output: undefined method `boom' for "foo":String
66
+ end
51
67
  ```
52
68
 
69
+ In this example, we attempt to call the non-existent method `boom` on the string `"foo"`.
70
+ `Defi` correctly raises a `NoMethodError`, showing that the method `boom` is undefined for a `String` object.
71
+
53
72
  ## Contact
54
73
 
55
74
  * Source code: https://github.com/fixrb/defi/issues
@@ -62,11 +81,6 @@ __Defi__ follows [Semantic Versioning 2.0](https://semver.org/).
62
81
 
63
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).
64
83
 
65
- ***
84
+ ## Sponsors
66
85
 
67
- <p>
68
- This project is sponsored by:<br />
69
- <a href="https://sashite.com/"><img
70
- src="https://github.com/fixrb/defi/raw/main/img/sashite.png"
71
- alt="Sashite" /></a>
72
- </p>
86
+ This project is sponsored by [Sashité](https://sashite.com/)
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Defi
4
+ # Represents a method to be applied against an object.
5
+ # Encapsulates method name, arguments, keyword arguments and blocks
6
+ # for dynamic method invocation with proper error handling.
7
+ class Method < ::BasicObject
8
+ # Initialize a new Method object.
9
+ #
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
16
+ def initialize(name, *args, **opts, &block)
17
+ raise ::ArgumentError, "Method name must be a Symbol, got: #{name.class}" unless name.is_a?(::Symbol)
18
+
19
+ @name = name
20
+ @args = args
21
+ @opts = opts
22
+ @block = block
23
+ end
24
+
25
+ # Applies the method to the given object.
26
+ #
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
32
+ #
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
39
+ def to(object)
40
+ Value.new { object.public_send(@name, *@args, **@opts, &@block) }
41
+ end
42
+
43
+ # @return [Hash] Method properties
44
+ def to_h
45
+ {
46
+ name: @name,
47
+ args: @args,
48
+ opts: @opts,
49
+ block: @block
50
+ }
51
+ end
52
+
53
+ # @return [String] Human-readable representation
54
+ #
55
+ # @example
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
67
+ #
68
+ # @example
69
+ # Defi::Method.new(:+, 1).to_s # => ".+(1)"
70
+ # Defi::Method.new(:map) { |x| x }.to_s # => ".map(<Proc>)"
71
+ def to_s
72
+ return ".#{@name}" if no_arguments?
73
+
74
+ ".#{@name}(#{stringified_arguments})"
75
+ end
76
+
77
+ private
78
+
79
+ def no_arguments?
80
+ @args.empty? && @opts.empty? && @block.nil?
81
+ end
82
+
83
+ def stringified_arguments
84
+ [
85
+ args_string,
86
+ opts_string,
87
+ block_string
88
+ ].compact.join(", ")
89
+ end
90
+
91
+ def args_string
92
+ @args.inspect[1..-2] unless @args.empty?
93
+ end
94
+
95
+ def opts_string
96
+ @opts.inspect[1..-2] unless @opts.empty?
97
+ end
98
+
99
+ def block_string
100
+ "<Proc>" if @block
101
+ end
102
+ end
103
+ end
104
+
105
+ require_relative "value"
data/lib/defi/value.rb CHANGED
@@ -1,68 +1,85 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Defi
4
- # This class contains an object that returned or raised during the initialize.
5
- #
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.
6
10
  class Value
7
- # @return [#object_id] The returned or the raised object.
11
+ RAISE = "raise"
12
+ RETURN = "return"
13
+
14
+ # @return [#object_id] The returned value or caught exception
8
15
  attr_reader :object
9
16
 
10
- # Initialize the value class.
17
+ # Initializes a Value object by executing the provided block.
18
+ #
19
+ # @example Successful execution
20
+ # value = Defi::Value.new { 1 + 1 }
21
+ # value.call # => 2
22
+ # value.raised? # => false
23
+ #
24
+ # @example Exception handling
25
+ # value = Defi::Value.new { raise TypeError, "Invalid type" }
26
+ # value.raised? # => true
27
+ # value.object # => #<TypeError: Invalid type>
11
28
  #
12
- # @yieldreturn [#object_id] The challenged code.
13
- # rubocop:disable Lint/RescueException
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.
32
+ #
33
+ # @yieldreturn [#object_id] Result or exception from block execution
14
34
  def initialize
15
35
  @object = yield
16
36
  @raised = false
17
- rescue ::Exception => e
37
+ rescue ::Exception => e # rubocop:disable Lint/RescueException
18
38
  @object = e
19
39
  @raised = true
20
40
  end
21
- # rubocop:enable Lint/RescueException
22
41
 
23
- # Raise or return the value.
42
+ # Returns the result or raises the captured exception.
43
+ #
44
+ # @example With successful result
45
+ # Value.new { "success" }.call # => "success"
24
46
  #
25
- # @return [#object_id] Raised exception or returned object.
47
+ # @example With exception
48
+ # Value.new { raise "error" }.call # raises RuntimeError: error
49
+ #
50
+ # @return [#object_id] The operation result
51
+ # @raise [Exception] The captured exception if raised? is true
26
52
  def call
27
53
  raise object if raised?
28
54
 
29
55
  object
30
56
  end
31
57
 
32
- # @return [Boolean] The value was raised (or returned)?
58
+ # @return [Boolean] true if execution raised an exception
33
59
  def raised?
34
60
  @raised
35
61
  end
36
62
 
37
- # Properties of the value.
38
- #
39
- # @return [Hash] The properties of the value.
63
+ # @return [String] Human-readable representation
64
+ def inspect
65
+ "Value(object: #{object}, raised: #{raised?})"
66
+ end
67
+
68
+ # @return [Hash] Value properties
40
69
  def to_h
41
- {
42
- raised: raised?,
43
- object: object
44
- }
70
+ { raised: raised?, object: }
45
71
  end
46
72
 
47
- # String of the value.
48
- #
49
- # @return [String] The string representation of the value.
73
+ # @return [String] String representation showing outcome type and value
50
74
  def to_s
51
75
  "#{raise_or_return} #{object}"
52
76
  end
53
77
 
54
- # A string containing a human-readable representation of the value.
55
- #
56
- # @return [String] The human-readable representation of the value.
57
- def inspect
58
- "Value(object: #{object}, raised: #{raised?})"
59
- end
60
-
61
78
  private
62
79
 
63
- # @return [String] A "raise" or "return" string.
80
+ # @return [String] Execution outcome type
64
81
  def raise_or_return
65
- raised? ? "raise" : "return"
82
+ raised? ? RAISE : RETURN
66
83
  end
67
84
  end
68
85
  end
data/lib/defi.rb CHANGED
@@ -2,21 +2,33 @@
2
2
 
3
3
  # Namespace for the Defi library.
4
4
  #
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
+ #
9
+ # @example Basic arithmetic operation
10
+ # addition = Defi(:+, 2)
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"
20
+ #
21
+ # @example Block usage
22
+ # map_double = Defi(:map) { |x| x * 2 }
23
+ # map_double.to([1, 2, 3]).call # => [2, 4, 6]
24
+ #
25
+ # @example Error handling
26
+ # result = Defi(:undefined_method).to(42)
27
+ # result.raised? # => true
28
+ # result.object # => #<NoMethodError: ...>
29
+ #
5
30
  module Defi
6
- # Expectations are built with this method.
7
- #
8
- # @example A :foo challenge
9
- # send(:foo) # => #<Defi::Challenge:0x007f96a40925f8 @method=:foo, @args=[]>
10
- #
11
- # @param method [#to_sym] The method to send to an object.
12
- # @param args [Array] Any arguments of the method.
13
- # @param kwargs [Hash] Any keyword arguments of the method.
14
- # @param block [Proc] Any block argument of the method.
15
- #
16
- # @return [Challenge] The challenge instance.
17
- def self.send(method, *args, **kwargs, &block)
18
- Challenge.new(method, *args, **kwargs, &block)
19
- end
20
31
  end
21
32
 
22
- require_relative File.join("defi", "challenge")
33
+ # Load core components
34
+ require_relative "kernel"
data/lib/kernel.rb ADDED
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative File.join("defi", "method")
4
+
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
+ module Kernel
10
+ # rubocop:disable Naming/MethodName
11
+
12
+ # Creates a new Defi::Method instance.
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.
15
+ #
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
+ #
21
+ # @example Basic method without arguments
22
+ # Defi(:to_s)
23
+ #
24
+ # @example Method with positional arguments
25
+ # Defi(:+, 2)
26
+ # Defi(:[], 0, 2) # For array/string slicing
27
+ #
28
+ # @example Method with keyword arguments
29
+ # Defi(:transform, x: 1, y: 2)
30
+ #
31
+ # @example Method with a block
32
+ # Defi(:map) { |x| x * 2 }
33
+ #
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)
42
+ end
43
+
44
+ # rubocop:enable Naming/MethodName
45
+ end
metadata CHANGED
@@ -1,141 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: defi
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.7
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: 2022-04-02 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: aw
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: 0.2.0
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: 0.2.0
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: rake
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: rubocop-md
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rubocop-performance
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: rubocop-rake
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rubocop-thread_safety
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: simplecov
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: yard
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
11
+ date: 2024-12-31 00:00:00.000000000 Z
12
+ dependencies: []
139
13
  description: Challenge library.
140
14
  email: contact@cyril.email
141
15
  executables: []
@@ -145,14 +19,15 @@ files:
145
19
  - LICENSE.md
146
20
  - README.md
147
21
  - lib/defi.rb
148
- - lib/defi/challenge.rb
22
+ - lib/defi/method.rb
149
23
  - lib/defi/value.rb
24
+ - lib/kernel.rb
150
25
  homepage: https://github.com/fixrb/defi
151
26
  licenses:
152
27
  - MIT
153
28
  metadata:
154
29
  rubygems_mfa_required: 'true'
155
- post_install_message:
30
+ post_install_message:
156
31
  rdoc_options: []
157
32
  require_paths:
158
33
  - lib
@@ -160,15 +35,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
160
35
  requirements:
161
36
  - - ">="
162
37
  - !ruby/object:Gem::Version
163
- version: 2.7.0
38
+ version: 3.1.0
164
39
  required_rubygems_version: !ruby/object:Gem::Requirement
165
40
  requirements:
166
41
  - - ">="
167
42
  - !ruby/object:Gem::Version
168
43
  version: '0'
169
44
  requirements: []
170
- rubygems_version: 3.1.6
171
- signing_key:
45
+ rubygems_version: 3.3.27
46
+ signing_key:
172
47
  specification_version: 4
173
48
  summary: Challenge library.
174
49
  test_files: []
@@ -1,99 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "aw"
4
-
5
- module Defi
6
- # This class contains a challenge to apply against an object.
7
- class Challenge < ::BasicObject
8
- # Initialize the challenge class.
9
- #
10
- # @param method [#to_sym] The method to send to an object.
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
- def initialize(method, *args, **opts, &block)
15
- @method = method.to_sym
16
- @args = args
17
- @opts = opts
18
- @block = block
19
- end
20
-
21
- # @param object [#object_id] The object to challenge.
22
- #
23
- # @return [Defi::Value] The actual value, to raise or to return.
24
- def to(object)
25
- Value.new { object.public_send(@method, *@args, **@opts, &@block) }
26
- end
27
-
28
- # @param object [#object_id] The object to challenge in code isolation.
29
- #
30
- # @return [Defi::Value] The actual value, to raise or to return.
31
- #
32
- # @see to
33
- def to!(object)
34
- ::Aw.fork! { to(object) }
35
- end
36
-
37
- # Properties of the challenge.
38
- #
39
- # @return [Hash] The properties of the challenge.
40
- def to_h
41
- {
42
- method: @method,
43
- args: @args,
44
- opts: @opts,
45
- block: @block
46
- }
47
- end
48
-
49
- # rubocop:disable Metrics/AbcSize
50
- # rubocop:disable Metrics/CyclomaticComplexity
51
- # rubocop:disable Metrics/MethodLength
52
-
53
- # String of the challenge.
54
- #
55
- # @return [String] The string representation of the challenge.
56
- def to_s
57
- string = ".#{@method}"
58
-
59
- return string if @args.empty? && @opts.empty? && @block.nil?
60
-
61
- stringified_args = @args.inspect[1..-2]
62
- stringified_opts = @opts.inspect[1..-2]
63
- stringified_block = "<Proc>" unless @block.nil?
64
-
65
- string += "("
66
-
67
- stringified_items = []
68
-
69
- stringified_items << stringified_args unless @args.empty?
70
- stringified_items << stringified_opts unless @opts.empty?
71
- stringified_items << stringified_block unless @block.nil?
72
-
73
- "#{string}#{stringified_items.join(", ")})"
74
- end
75
-
76
- # rubocop:enable Metrics/AbcSize
77
- # rubocop:enable Metrics/CyclomaticComplexity
78
- # rubocop:enable Metrics/MethodLength
79
-
80
- # A string containing a human-readable representation of the challenge.
81
- #
82
- # @return [String] The human-readable representation of the challenge.
83
- def inspect
84
- inspected_method = @method.inspect
85
- inspected_args = @args.inspect
86
- inspected_opts = @opts.inspect
87
- inspected_block = @block.nil? ? "nil" : "<Proc>"
88
-
89
- "Defi(" \
90
- "method: #{inspected_method}, " \
91
- "args: #{inspected_args}, " \
92
- "opts: #{inspected_opts}, " \
93
- "block: #{inspected_block}" \
94
- ")"
95
- end
96
- end
97
- end
98
-
99
- require_relative "value"