Class: Cuprum::Command

Inherits:
Object
  • Object
show all
Includes:
Currying, Processing, Steps
Defined in:
lib/cuprum/command.rb

Overview

Functional object that encapsulates a business logic operation or step.

Using commands allows the developer to maintain a state or context, such as by passing context into the constructor. It provides a consistent interface by always returning a Cuprum::Result object, which tracks the status of the command call, the returned value, and the error object (if any). Finally, as a full-fledged Ruby object a Command can be passed around like any other object, including returned from a method (or another Command) or passed in as a parameter.

A Command can be defined either by passing a block to the constructor, or by defining a subclass of Command and implementing the #process method.

Examples:

A Command with a block

double_command = Cuprum::Command.new { |int| 2 * int }
result         = double_command.call(5)

result.value #=> 10

A Command subclass

class MultiplyCommand < Cuprum::Command
  def initialize(multiplier)
    @multiplier = multiplier
  end

  private def process(int)
    int * @multiplier
  end
end

triple_command = MultiplyCommand.new(3)
result         = command_command.call(5)

result.value #=> 15

A Command with an error state

class DivideCommand < Cuprum::Command
  def initialize(divisor)
    @divisor = divisor
  end

  private def process(int)
    if @divisor.zero?
      return Cuprum::Result.new(error: 'errors.messages.divide_by_zero')
    end

    int / @divisor
  end
end

halve_command = DivideCommand.new(2)
result        = halve_command.call(10)

result.error #=> nil
result.value #=> 5

divide_command = DivideCommand.new(0)
result         = divide_command.call(10)

result.error #=> 'errors.messages.divide_by_zero'
result.value #=> nil

See Also:

Instance Method Summary collapse

Methods included from Steps

#step, #steps

Methods included from Currying

#curry

Methods included from Processing

#arity, #process

Constructor Details

#initialize {|arguments, keywords, block| ... } ⇒ Command

Returns a new instance of Cuprum::Command.

Yields:

  • If a block is given, the block is used to define a private #process method. This overwrites any existing #process method. When the command is called, #process will be called internally and passed the parameters.

Yield Parameters:

  • arguments (Array)

    the arguments passed to #call.

  • keywords (Hash)

    the keywords passed to #call.

  • block (Proc, nil)

    the block passed to call, #if any.

Yield Returns:

  • (Cuprum::Result, Object)

    the returned result or object is converted to a Cuprum::Result and returned by #call.



88
89
90
91
92
93
94
# File 'lib/cuprum/command.rb', line 88

def initialize(&implementation)
  return unless implementation

  define_singleton_method :process, &implementation

  singleton_class.send(:private, :process)
end

Instance Method Details

#call(*arguments, **keywords) { ... } ⇒ Cuprum::Result

Executes the command and returns a Cuprum::Result or compatible object.

Each time #call is invoked, the object performs the following steps:

  1. The #process method is called, passing the arguments, keywords, and block that were passed to #call.

  2. If the value returned by #process is a Cuprum::Result or compatible object, that result is directly returned by #call.

  3. Otherwise, the value returned by #process will be wrapped in a successful result, which will be returned by #call.

Parameters:

  • arguments (Array)

    Arguments to be passed to the implementation.

  • keywords (Hash)

    Keywords to be passed to the implementation.

Yields:

  • If a block argument is given, it will be passed to the implementation.

Returns:



97
98
99
# File 'lib/cuprum/command.rb', line 97

def call(*args, **kwargs, &block)
  steps { super }
end

#to_procProc

Wraps the command in a proc.

Calling the proc will call the command with the given arguments, keywords, and block.

Returns:

  • (Proc)

    the wrapping proc.



107
108
109
110
111
112
113
114
115
116
117
# File 'lib/cuprum/command.rb', line 107

def to_proc
  command = self

  @to_proc ||= lambda do |*args, **kwargs, &block|
    if kwargs.empty?
      command.call(*args, &block)
    else
      command.call(*args, **kwargs, &block)
    end
  end
end