Cuprum

An opinionated implementation of the Command pattern for Ruby applications. Cuprum wraps your business logic in a consistent, object-oriented interface and features status and error management, composability and control flow management.

Class: Cuprum::Matcher

Parent Namespace
Cuprum
Extended Modules
Cuprum::Matching::ClassMethods
Included Modules
Cuprum::Matching
Defined In
lib/cuprum/matcher.rb

Table Of Contents

Overview

Provides result matching based on result status, error, and value.

First, define match clauses using the .match DSL. Each match clause has a status and optionally a value class and/or error class. A result will only match the clause if the result status is the same as the clause’s status. If the clause sets a value class, then the result value must be an instance of that class (or an instance of a subclass). If the clause sets an error class, then the result error must be an instance of that class (or an instance of a subclass).

Once the matcher defines one or more match clauses, call #call with a result to match the result. The matcher will determine the best match with the same status (value and error match the result, only value or error match, or just status matches) and then call the match clause with the result. If no match clauses match the result, the matcher will instead raise a Cuprum::Matching::NoMatchError.

Examples

Matching A Status

matcher = Cuprum::Matcher.new do
  match(:failure) { 'Something went wrong' }

  match(:success) { 'Ok' }
end

matcher.call(Cuprum::Result.new(status: :failure))
#=> 'Something went wrong'

matcher.call(Cuprum::Result.new(status: :success))
#=> 'Ok'

Matching An Error

matcher = Cuprum::Matcher.new do
  match(:failure) { 'Something went wrong' }

  match(:failure, error: CustomError) { |result| result.error.message }

  match(:success) { 'Ok' }
end

matcher.call(Cuprum::Result.new(status: :failure))
#=> 'Something went wrong'

error = CustomError.new(message: 'The magic smoke is escaping.')
matcher.call(Cuprum::Result.new(error: error))
#=> 'The magic smoke is escaping.'

Using A Match Context

context = Struct.new(:name).new('programs')
matcher = Cuprum::Matcher.new(context) do
  match(:failure) { 'Something went wrong' }

  match(:success) { "Greetings, #{name}!" }
end

matcher.call(Cuprum::Result.new(status: :success)
#=> 'Greetings, programs!'

Back To Top

Class Methods

.match(status, error: nil, value: nil, &block) => Object

Inherited From
Cuprum::Matching::ClassMethods

Defines a match clause for the matcher.

Parameters

Yields

Yield Parameters

Back To Top

Constructor

#initialize(match_context = nil, &) => Matcher

Parameters

Yields

Returns

Back To Top

Instance Methods

#call(result) => Object

Inherited From
Cuprum::Matching

Finds the match clause matching the result and calls the stored block.

Match clauses are defined using the .match DSL. When a result is matched, the defined clauses matching the result status are checked in descending order of specificity:

If there are multiple clauses that expect a value or an error, they are sorted by inheritance - a clause with a subclass value or error is checked before the clause with the parent class.

Using that ordering, each potential clause is checked for a match with the result. If the clause defines a value, then the result will match the clause only if the result value is an instance of the expected value (or an instance of a subclass). Likewise, if the clause defines an error, then the result will match the clause only if the result error is an instance of the expected error class (or an instance of a subclass). Clauses that do not define either a value nor an error will match with any result with the same status, but as the least specific are always matched last.

Matchers can also inherit clauses from a parent class or from an included module. Inherited or included clauses are checked after clauses defined on the matcher itself, so the matcher can override generic matches with more specific functionality.

Finally, once the most specific matching clause is found, #call will call the block used to define the clause. If the block takes at least one argument, the result will be passed to the block; otherwise, it will be called with no parameters. If there is no clause matching the result, #call will instead raise a Cuprum::Matching::NoMatchError.

The match clause is executed in the context of the matcher object. This allows instance methods defined for the matcher to be called as part of the match clause block. If the matcher defines a non-nil #matching_context, the block is instead executed in the context of the matching_context using #instance_exec.

Parameters

Returns

Raises

See Also

#match_context? => Boolean

Inherited From
Cuprum::Matching

Returns

#matches?(result) => Boolean
#matches?(status, error: nil, value: nil) => Boolean

Inherited From
Cuprum::Matching

Overloads

#matches?(result) => Boolean

Checks if the matcher has any match clauses that match the given result.

Parameters
Returns
  • (Boolean) — true if the matcher has at least one match clause that matches the result; otherwise false.
#matches?(status, error: nil, value: nil) => Boolean

Checks if the matcher has any clauses matching the status and details.

Parameters
  • status (Symbol) — The status to match.
  • error (Class, nil) — The class of error to match, if any.
  • value (Class, nil) — The class of value to match, if any.
Returns
  • (Boolean) — true if the matcher has at least one match clause that matches the status and details; otherwise false.

Raises

#with_context(match_context) => Cuprum::Matcher

Also known as: using_context

Returns a copy of the matcher with the given execution context.

Parameters

Returns

Back To Top


Back to Documentation | Reference | Cuprum