cuprum 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -24,6 +24,10 @@ module Cuprum::BuiltIn
24
24
  # result.error
25
25
  # #=> 'errors.messages.unknown'
26
26
  class IdentityCommand < Cuprum::Command
27
+ def initialize
28
+ super(&nil)
29
+ end
30
+
27
31
  private
28
32
 
29
33
  def process(value = nil)
@@ -14,15 +14,15 @@ module Cuprum::BuiltIn
14
14
  # #=> true
15
15
  #
16
16
  # @example With a result.
17
- # errors = ['errors.messages.unknown']
18
- # value = Cuprum::Result.new('result value', :errors => errors)
17
+ # error = 'errors.messages.unknown'
18
+ # value = Cuprum::Result.new(value: 'result value', error: error)
19
19
  # operation = IdentityOperation.new.call(value)
20
20
  # operation.value
21
21
  # #=> 'result value'
22
22
  # operation.success?
23
23
  # #=> false
24
- # operation.errors
25
- # #=> ['errors.messages.unknown']
24
+ # operation.error
25
+ # #=> 'errors.messages.unknown'
26
26
  class IdentityOperation < Cuprum::BuiltIn::IdentityCommand
27
27
  include Cuprum::Operation::Mixin
28
28
  end
@@ -13,8 +13,12 @@ module Cuprum::BuiltIn
13
13
  # result.success?
14
14
  # #=> true
15
15
  class NullCommand < Cuprum::Command
16
+ def initialize
17
+ super(&nil)
18
+ end
19
+
16
20
  private
17
21
 
18
- def process(*_args); end
22
+ def process(*_args, **_kwargs); end
19
23
  end
20
24
  end
@@ -5,8 +5,15 @@ require 'cuprum/processing'
5
5
  require 'cuprum/steps'
6
6
 
7
7
  module Cuprum
8
- # Functional object that encapsulates a business logic operation with a
9
- # consistent interface and tracking of result value and status.
8
+ # Functional object that encapsulates a business logic operation or step.
9
+ #
10
+ # Using commands allows the developer to maintain a state or context, such as
11
+ # by passing context into the constructor. It provides a consistent interface
12
+ # by always returning a Cuprum::Result object, which tracks the status of the
13
+ # command call, the returned value, and the error object (if any). Finally, as
14
+ # a full-fledged Ruby object a Command can be passed around like any other
15
+ # object, including returned from a method (or another Command) or passed in
16
+ # as a parameter.
10
17
  #
11
18
  # A Command can be defined either by passing a block to the constructor, or
12
19
  # by defining a subclass of Command and implementing the #process method.
@@ -19,13 +26,11 @@ module Cuprum
19
26
  #
20
27
  # @example A Command subclass
21
28
  # class MultiplyCommand < Cuprum::Command
22
- # def initialize multiplier
29
+ # def initialize(multiplier)
23
30
  # @multiplier = multiplier
24
31
  # end
25
32
  #
26
- # private
27
- #
28
- # def process int
33
+ # private def process(int)
29
34
  # int * @multiplier
30
35
  # end
31
36
  # end
@@ -37,13 +42,11 @@ module Cuprum
37
42
  #
38
43
  # @example A Command with an error state
39
44
  # class DivideCommand < Cuprum::Command
40
- # def initialize divisor
45
+ # def initialize(divisor)
41
46
  # @divisor = divisor
42
47
  # end
43
48
  #
44
- # private
45
- #
46
- # def process int
49
+ # private def process(int)
47
50
  # if @divisor.zero?
48
51
  # return Cuprum::Result.new(error: 'errors.messages.divide_by_zero')
49
52
  # end
@@ -72,10 +75,16 @@ module Cuprum
72
75
 
73
76
  # Returns a new instance of Cuprum::Command.
74
77
  #
75
- # @yield [*arguments, **keywords, &block] If a block is given, the
76
- # #call method will wrap the block and set the result #value to the return
77
- # value of the block. This overrides the implementation in #process, if
78
- # any.
78
+ # @yield If a block is given, the block is used to define a private #process
79
+ # method. This overwrites any existing #process method. When the command
80
+ # is called, #process will be called internally and passed the parameters.
81
+ #
82
+ # @yieldparam arguments [Array] the arguments passed to #call.
83
+ # @yieldparam keywords [Hash] the keywords passed to #call.
84
+ # @yieldparam block [Proc, nil] the block passed to call, #if any.
85
+ #
86
+ # @yieldreturn [Cuprum::Result, Object] the returned result or object is
87
+ # converted to a Cuprum::Result and returned by #call.
79
88
  def initialize(&implementation)
80
89
  return unless implementation
81
90
 
@@ -96,11 +105,13 @@ module Cuprum
96
105
  #
97
106
  # @return [Proc] the wrapping proc.
98
107
  def to_proc
108
+ command = self
109
+
99
110
  @to_proc ||= lambda do |*args, **kwargs, &block|
100
111
  if kwargs.empty?
101
- call(*args, &block)
112
+ command.call(*args, &block)
102
113
  else
103
- call(*args, **kwargs, &block)
114
+ command.call(*args, **kwargs, &block)
104
115
  end
105
116
  end
106
117
  end
@@ -9,11 +9,11 @@ module Cuprum
9
9
  #
10
10
  # @example
11
11
  # class SpaceFactory < Cuprum::CommandFactory
12
- # command :build, BuildCommand
12
+ # command(:build, BuildCommand)
13
13
  #
14
- # command :fly { |launch_site:| FlyCommand.new(launch_site) }
14
+ # command(:fly) { |launch_site:| FlyCommand.new(launch_site) }
15
15
  #
16
- # command_class :dream { DreamCommand }
16
+ # command_class(:dream) { DreamCommand }
17
17
  # end
18
18
  #
19
19
  # factory = SpaceFactory.new
@@ -81,7 +81,7 @@ module Cuprum
81
81
  #
82
82
  # @yield The block will be executed in the context of the factory
83
83
  # instance.
84
- # @yieldparam *args [Array] Any arguments given to the method
84
+ # @yieldparam args [Array] Any arguments given to the method
85
85
  # factory.name() will be passed on the block.
86
86
  # @yieldreturn [Cuprum::Command] The block return an instance of a
87
87
  # Cuprum::Command subclass, or else raise an error.
@@ -3,7 +3,7 @@
3
3
  require 'cuprum/currying'
4
4
 
5
5
  module Cuprum::Currying
6
- # A CurriedCommand wraps another command and passes preset args to #call.
6
+ # A CurriedCommand wraps another command and passes preset params to #call.
7
7
  #
8
8
  # @example Currying Arguments
9
9
  # # Our base command takes two arguments.
data/lib/cuprum/error.rb CHANGED
@@ -7,6 +7,48 @@ module Cuprum
7
7
  #
8
8
  # Additional details can be passed by setting the #message or by using a
9
9
  # subclass of Cuprum::Error.
10
+ #
11
+ # @example
12
+ # error = Cuprum::Error.new(message: 'Something went wrong')
13
+ # error.type
14
+ # #=> 'cuprum.error'
15
+ # error.message
16
+ # #=> 'Something went wrong'
17
+ #
18
+ # @example An Error With Custom Type
19
+ # error = Cuprum::Error.new(
20
+ # message: 'Something went wrong',
21
+ # type: 'custom.errors.generic',
22
+ # )
23
+ # error.type
24
+ # #=> 'custom.errors.generic'
25
+ #
26
+ # @example An Error Subclass
27
+ # class LightsError < Cuprum::Error
28
+ # TYPE = 'custom.errors.wrong_number_of_lights'
29
+ #
30
+ # def initialize(count)
31
+ # super(message: "There are #{count} lights!")
32
+ #
33
+ # @count = count
34
+ # end
35
+ #
36
+ # private def as_json_data
37
+ # { 'count' => count }
38
+ # end
39
+ # end
40
+ #
41
+ # error = LightsError.new(4)
42
+ # error.type
43
+ # #=> 'custom.errors.wrong_number_of_lights'
44
+ # error.message
45
+ # #=> 'There are 4 lights!'
46
+ # error.as_json
47
+ # #=> {
48
+ # # 'data' => { 'count' => 4 },
49
+ # # 'message' => 'There are 4 lights!',
50
+ # # 'type' => 'custom.errors.wrong_number_of_lights'
51
+ # # }
10
52
  class Error
11
53
  # Short string used to identify the type of error.
12
54
  #
@@ -4,14 +4,13 @@ require 'cuprum/error'
4
4
  require 'cuprum/errors'
5
5
 
6
6
  module Cuprum::Errors
7
- # Error class to be used when a Command is called without defining a #process
8
- # method.
7
+ # Error returned when a Command is called without defining a #process method.
9
8
  class CommandNotImplemented < Cuprum::Error
10
9
  COMPARABLE_PROPERTIES = %i[command].freeze
11
10
  private_constant :COMPARABLE_PROPERTIES
12
11
 
13
- # Format for generating error message.
14
12
  MESSAGE_FORMAT = 'no implementation defined for %s'
13
+ private_constant :MESSAGE_FORMAT
15
14
 
16
15
  # Short string used to identify the type of error.
17
16
  TYPE = 'cuprum.errors.command_not_implemented'
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum/error'
4
+ require 'cuprum/errors'
5
+
6
+ module Cuprum::Errors
7
+ # Error wrapping multiple errors from a collection command.
8
+ class MultipleErrors < Cuprum::Error
9
+ # Short string used to identify the type of error.
10
+ TYPE = 'cuprum.errors.multiple_errors'
11
+
12
+ # @param errors [Array<Cuprum::Error>] The wrapped errors.
13
+ # @param message [String] Optional message describing the nature of the
14
+ # error.
15
+ def initialize(errors:, message: nil)
16
+ @errors = errors
17
+
18
+ super(
19
+ errors: errors,
20
+ message: message || default_message
21
+ )
22
+ end
23
+
24
+ # @return [Array<Cuprum::Error>] the wrapped errors.
25
+ attr_reader :errors
26
+
27
+ private
28
+
29
+ def as_json_data
30
+ {
31
+ 'errors' => errors.map { |error| error&.as_json }
32
+ }
33
+ end
34
+
35
+ def default_message
36
+ 'the command encountered one or more errors'
37
+ end
38
+ end
39
+ end
@@ -4,11 +4,10 @@ require 'cuprum/error'
4
4
  require 'cuprum/errors'
5
5
 
6
6
  module Cuprum::Errors
7
- # Error class to be used when trying to access the result of an uncalled
8
- # Operation.
7
+ # Error returned when trying to access the result of an uncalled Operation.
9
8
  class OperationNotCalled < Cuprum::Error
10
- # Format for generating error message.
11
9
  MESSAGE_FORMAT = '%s was not called and does not have a result'
10
+ private_constant :MESSAGE_FORMAT
12
11
 
13
12
  # Short string used to identify the type of error.
14
13
  TYPE = 'cuprum.errors.operation_not_called'
@@ -4,7 +4,7 @@ require 'cuprum/error'
4
4
  require 'cuprum/errors'
5
5
 
6
6
  module Cuprum::Errors
7
- # An error returned when a command encounters an unhandled exception.
7
+ # Error returned when a command encounters an unhandled exception.
8
8
  class UncaughtException < Cuprum::Error
9
9
  # Short string used to identify the type of error.
10
10
  TYPE = 'cuprum.collections.errors.uncaught_exception'
@@ -45,7 +45,7 @@ module Cuprum::Errors
45
45
  end
46
46
 
47
47
  def generate_message(message)
48
- message = "#{message} #{exception.class}: #{exception.message}"
48
+ message = "#{message.rstrip} #{exception.class}: #{exception.message}"
49
49
 
50
50
  return message unless cause
51
51
 
data/lib/cuprum/errors.rb CHANGED
@@ -4,5 +4,10 @@ require 'cuprum'
4
4
 
5
5
  module Cuprum
6
6
  # Namespace for custom Cuprum error classes.
7
- module Errors; end
7
+ module Errors
8
+ autoload :CommandNotImplemented, 'cuprum/errors/command_not_implemented'
9
+ autoload :MultipleErrors, 'cuprum/errors/multiple_errors'
10
+ autoload :OperationNotCalled, 'cuprum/errors/operation_not_called'
11
+ autoload :UncaughtException, 'cuprum/errors/uncaught_exception'
12
+ end
8
13
  end
@@ -3,7 +3,7 @@
3
3
  require 'cuprum/errors/uncaught_exception'
4
4
 
5
5
  module Cuprum
6
- # Utility class for handling uncaught exceptions in commands.
6
+ # Utility module for handling uncaught exceptions in commands.
7
7
  #
8
8
  # @example
9
9
  # class UnsafeCommand < Cuprum::Command
@@ -27,7 +27,7 @@ module Cuprum
27
27
  # #=> a Cuprum::Errors::UncaughtException error.
28
28
  # result.error.message
29
29
  # #=> 'uncaught exception in SafeCommand -' \
30
- # ' StandardError: Something went wrong.'
30
+ # # ' StandardError: Something went wrong.'
31
31
  module ExceptionHandling
32
32
  # Wraps the #call method with a rescue clause matching any StandardError.
33
33
  #
@@ -37,6 +37,8 @@ module Cuprum
37
37
  #
38
38
  # @return [Cuprum::Result] the result of calling the superclass method, or
39
39
  # a failing result if a StandardError is raised.
40
+ #
41
+ # @see Cuprum::Processing#call
40
42
  def call(*args, **kwargs, &block)
41
43
  super
42
44
  rescue StandardError => exception
@@ -0,0 +1,227 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cuprum'
4
+
5
+ module Cuprum
6
+ # Calls the command implementation with each item in the given enumerable.
7
+ #
8
+ # A regular Command is called with a set of parameters, calls the command
9
+ # implementation once with those parameters, and returns the Result. In
10
+ # contrast, a MapCommand is called with an Enumerable object, such as an
11
+ # Array, a Hash, or an Enumerator (e.g. by calling #each without a block). The
12
+ # MapCommand implementation is then called with each item in the
13
+ # Enumerable - for example, if called with an Array with three items, the
14
+ # MapCommand implementation would be called three times, once with each item.
15
+ # Finally, the Results returned by calling the implementation with each item
16
+ # are aggregated together into a Cuprum::ResultList. A ResultList behaves like
17
+ # a Result, and provides the standard methods (such as #status, #error, and
18
+ # #value), but also includes a reference to the #results used to create the
19
+ # ResultList, and their respective #errors and #values as Arrays.
20
+ #
21
+ # Like a standard Command, a MapCommand can be defined either by passing a
22
+ # block to the constructor, or by defining a subclass of MapCommand and
23
+ # implementing the #process method. If the given block or the #process method
24
+ # accepts more than one argument, the enumerable item is destructured using
25
+ # the splat operator (*); this enables using a MapCommand to map over the keys
26
+ # and values of a Hash. This is the same behavior seen when passing a block
27
+ # with multiple arguments to a native #each method.
28
+ #
29
+ # If a MapCommand is initialized with the :allow_partial keyword, the
30
+ # ResultList will be passing as long as there is at least one passing Result
31
+ # (or if the MapCommand is called with an empty Enumerable). See
32
+ # ResultList#allow_partial? for details.
33
+ #
34
+ # @example A MapCommand with a block
35
+ # titleize_command = Cuprum::MapCommand.new do |str|
36
+ # if str.nil? || str.empty?
37
+ # next failure(Cuprum::Error.new(message: "can't be blank"))
38
+ # end
39
+ #
40
+ # str.split(' ').map(&:capitalize).join(' ')
41
+ # end
42
+ #
43
+ # @example A MapCommand Subclass
44
+ # class TitleizeCommand < Cuprum::MapCommand
45
+ # private
46
+ #
47
+ # def process(str)
48
+ # if str.nil? || str.empty?
49
+ # return failure(Cuprum::Error.new(message: "can't be blank"))
50
+ # end
51
+ #
52
+ # str.split(' ').map(&:capitalize).join(' ')
53
+ # end
54
+ # end
55
+ #
56
+ # titleize_command = TitleizeCommand.new
57
+ #
58
+ # @example With an Array with passing Results
59
+ # results = titleize_command.call(['hello world', 'greetings programs'])
60
+ # results.class
61
+ # #=> Cuprum::ResultsList
62
+ # results.status
63
+ # #=> :success
64
+ # results.value
65
+ # #=> ['Hello World', 'Greetings Programs']
66
+ # results.values
67
+ # #=> ['Hello World', 'Greetings Programs']
68
+ # results.error
69
+ # #=> nil
70
+ # results.errors
71
+ # #=> [nil, nil]
72
+ #
73
+ # @example With an Array with failing Results
74
+ # results = titleize_command.call([nil, ''])
75
+ # results.status
76
+ # #=> :failure
77
+ # results.value
78
+ # #=> [nil, nil]
79
+ # results.values
80
+ # #=> [nil, nil]
81
+ # results.error.class
82
+ # #=> Cuprum::Errors::MultipleErrors
83
+ # results.errors.map(&:class)
84
+ # #=> [Cuprum::Error, Cuprum::Error]
85
+ # results.errors.first.message
86
+ # #=> "can't be blank"
87
+ #
88
+ # @example With an Array with mixed passing and failing Results
89
+ # results = titleize_command.call([nil, 'greetings programs'])
90
+ # results.status
91
+ # #=> :failure
92
+ # results.value
93
+ # #=> [nil, "Greetings Programs"]
94
+ # results.values
95
+ # #=> [nil, "Greetings Programs"]
96
+ # results.error.class
97
+ # #=> Cuprum::Errors::MultipleErrors
98
+ # results.errors.map(&:class)
99
+ # #=> [Cuprum::Error, nil]
100
+ # results.errors.first.message
101
+ # #=> "can't be blank"
102
+ #
103
+ # @example With an Empty Array
104
+ # results = titleize_command.call([])
105
+ # results.status
106
+ # #=> :success
107
+ # results.value
108
+ # #=> []
109
+ # results.values
110
+ # #=> []
111
+ # results.error
112
+ # #=> nil
113
+ # results.errors
114
+ # #=> []
115
+ #
116
+ # @example With a Hash
117
+ # inspect_command = Cuprum::MapCommand.new do |key, value|
118
+ # "#{key.inspect} => #{value.inspect}"
119
+ # end
120
+ #
121
+ # results = inspect_command.call({ ichi: 1, "ni" => 2 })
122
+ # results.status
123
+ # #=> :success
124
+ # results.value
125
+ # #=> [':ichi => 1', '"ni" => 2']
126
+ # results.values
127
+ # #=> [':ichi => 1', '"ni" => 2']
128
+ # results.error
129
+ # #=> nil
130
+ # results.errors
131
+ # #=> [nil, nil]
132
+ #
133
+ # @example With an Enumerable
134
+ # square_command = Cuprum::MapCommand.new { |i| i ** 2 }
135
+ #
136
+ # results = square_command.call(0...4)
137
+ # results.status
138
+ # #=> :success
139
+ # results.value
140
+ # #=> [0, 1, 4, 9]
141
+ # results.values
142
+ # #=> [0, 1, 4, 9]
143
+ #
144
+ # @example With allow_partial: true
145
+ # maybe_upcase_command = Cuprum::MapCommand.new do |str|
146
+ # next str.upcase if str.is_a?(String)
147
+ #
148
+ # failure(Cuprum::Error.new(message: 'not a String'))
149
+ # end
150
+ #
151
+ # results = maybe_upcase_command.call([nil, 'greetings', 'programs'])
152
+ # results.status
153
+ # #=> :success
154
+ # results.value
155
+ # #=> [nil, 'GREETINGS', 'PROGRAMS']
156
+ # results.values
157
+ # #=> [nil, 'GREETINGS', 'PROGRAMS']
158
+ # results.error.class
159
+ # #=> Cuprum::Errors::MultipleErrors
160
+ # results.errors.map(&:class)
161
+ # #=> [Cuprum::Error, nil, nil]
162
+ # results.errors.first.message
163
+ # #=> 'not a String'
164
+ #
165
+ # @see Cuprum::Command
166
+ # @see Cuprum::ResultList
167
+ class MapCommand < Cuprum::Command
168
+ # @overload initialize(allow_partial: false)
169
+ # @param allow_partial [true, false] If true, allows for some failing
170
+ # results as long as there is at least one passing result. Defaults to
171
+ # false.
172
+ #
173
+ # @overload initialize(allow_partial: false) { |item| }
174
+ # @param allow_partial [true, false] If true, allows for some failing
175
+ # results as long as there is at least one passing result. Defaults to
176
+ # false.
177
+ # @yield The command implementation, to be called with each successive
178
+ # item in the given enumerable. This overrides the #process method, if
179
+ # any.
180
+ # @yieldparam [Object] item Each item in the given Enumerable.
181
+ #
182
+ # @overload initialize(allow_partial: false) { |key, value| }
183
+ # @param allow_partial [true, false] If true, allows for some failing
184
+ # results as long as there is at least one passing result. Defaults to
185
+ # false.
186
+ # @yield The command implementation, to be called with each successive
187
+ # item in the given enumerable. This overrides the #process method, if
188
+ # any.
189
+ # @yieldparam [Object] key Each key in the given Hash.
190
+ # @yieldparam [Object] value Each value in the given Hash.
191
+ def initialize(allow_partial: false, &implementation)
192
+ super(&implementation)
193
+
194
+ @allow_partial = allow_partial
195
+ end
196
+
197
+ # @return [true, false] if true, allows for some failing results as long as
198
+ # there is at least one passing result. Defaults to false.
199
+ def allow_partial?
200
+ @allow_partial
201
+ end
202
+
203
+ # Calls the command implementation for each item in the given Enumerable.
204
+ #
205
+ # @param enumerable [Array, Hash, Enumerable] The collection or enumerable
206
+ # object to map.
207
+ #
208
+ # @return [Cuprum::ResultList] the aggregated results.
209
+ def call(enumerable)
210
+ build_result_list(
211
+ enumerable.map { |item| splat_items? ? super(*item) : super(item) }
212
+ )
213
+ end
214
+
215
+ private
216
+
217
+ def build_result_list(results)
218
+ Cuprum::ResultList.new(*results, allow_partial: allow_partial?)
219
+ end
220
+
221
+ def splat_items?
222
+ return @splat_items unless @splat_items.nil?
223
+
224
+ @splat_items = method(:process).arity > 1
225
+ end
226
+ end
227
+ end
@@ -63,6 +63,8 @@ module Cuprum
63
63
  class Matcher
64
64
  include Cuprum::Matching
65
65
 
66
+ # @!parse extend Cuprum::Matching::ClassMethods
67
+
66
68
  # @param match_context [Object] the execution context for a matching clause.
67
69
  #
68
70
  # @yield Executes the block in the context of the singleton class. This is
@@ -76,10 +76,10 @@ module Cuprum
76
76
  #
77
77
  # @param result [Cuprum::Result] The result to match.
78
78
  #
79
- # @raise Cuprum::Matching::NoMatchError if none of the matchers match the
79
+ # @raise [Cuprum::Matching::NoMatchError] if none of the matchers match the
80
80
  # given result.
81
81
  #
82
- # @see Cuprum::Matcher#call.
82
+ # @see Cuprum::Matching#call.
83
83
  def call(result)
84
84
  unless result.respond_to?(:to_cuprum_result)
85
85
  raise ArgumentError, 'result must be a Cuprum::Result'
@@ -114,6 +114,8 @@ module Cuprum
114
114
  end
115
115
  end
116
116
 
117
+ # @!parse extend ClassMethods
118
+
117
119
  # @return [Object, nil] the execution context for a matching clause.
118
120
  attr_reader :match_context
119
121
 
@@ -164,7 +166,7 @@ module Cuprum
164
166
  #
165
167
  # @raise [NoMatchError] if there is no clause matching the result.
166
168
  #
167
- # @see ClassMethods::match
169
+ # @see ClassMethods#match
168
170
  # @see #match_context
169
171
  def call(result)
170
172
  unless result.respond_to?(:to_cuprum_result)
@@ -62,7 +62,7 @@ module Cuprum
62
62
  # end
63
63
  # end
64
64
  #
65
- # command = Command.new { |**opts| "Called with #{opts.inspect}" }
65
+ # command = ExampleCommand.new
66
66
  # middleware = LoggingMiddleware.new
67
67
  # result = middleware.call(command, { id: 0 })
68
68
  # #=> logs "Calling command ExampleCommand"
@@ -81,8 +81,8 @@ module Cuprum
81
81
  # end
82
82
  # end
83
83
  #
84
- # command = Command.new { |**opts| "Called with #{opts.inspect}" }
85
- # middleware = LoggingMiddleware.new
84
+ # command = Command.new { |**options| "Options: #{options.inspect}" }
85
+ # middleware = ApiMiddleware.new
86
86
  # result = middleware.call(command, { id: 0 })
87
87
  # result.value
88
88
  # #=> "Options: { id: 0, api_key: '12345' }"
@@ -92,8 +92,8 @@ module Cuprum
92
92
  # include Cuprum::Middleware
93
93
  #
94
94
  # # The middleware runs the command once. On a failing result, the
95
- # # middleware discards the failing result and returns a result with a
96
- # # value of nil.
95
+ # # middleware discards the failing result and returns a passing result
96
+ # # with a value of nil.
97
97
  # private def process(next_command, *args, **kwargs)
98
98
  # result = super
99
99
  #
@@ -103,16 +103,23 @@ module Cuprum
103
103
  # end
104
104
  # end
105
105
  #
106
- # command = Command.new { |**opts| "Called with #{opts.inspect}" }
107
- # middleware = LoggingMiddleware.new
108
- # result = middleware.call(command, { id: 0 })
106
+ # middleware = IgnoreFailure.new
107
+ # command = Command.new do |number|
108
+ # return success('number is even') if number.even?
109
+ #
110
+ # error = Cuprum::Error.new(message: 'number is odd')
111
+ # failure(error)
112
+ # end
113
+ #
114
+ # # Calling the command without the middleware.
115
+ # result = command.call(1)
109
116
  # result.success?
110
- # #=> true
111
- # result.value
112
- # #=> "Options: { id: 0, api_key: '12345' }"
117
+ # #=> false
118
+ # result.error.message
119
+ # #=> 'number is odd'
113
120
  #
114
- # error = Cuprum::Error.new(message: 'Something went wrong.')
115
- # result = middleware.call(command, error: error)
121
+ # # Calling the command with the middleware.
122
+ # result = middleware.call(command, 1)
116
123
  # result.success?
117
124
  # #=> true
118
125
  # result.value