Class: Cuprum::MapCommand

Inherits:
Command
  • Object
show all
Defined in:
lib/cuprum/map_command.rb

Overview

Calls the command implementation with each item in the given enumerable.

A regular Command is called with a set of parameters, calls the command implementation once with those parameters, and returns the Result. In contrast, a MapCommand is called with an Enumerable object, such as an Array, a Hash, or an Enumerator (e.g. by calling #each without a block). The MapCommand implementation is then called with each item in the Enumerable - for example, if called with an Array with three items, the MapCommand implementation would be called three times, once with each item. Finally, the Results returned by calling the implementation with each item are aggregated together into a Cuprum::ResultList. A ResultList behaves like a Result, and provides the standard methods (such as #status, #error, and #value), but also includes a reference to the #results used to create the ResultList, and their respective #errors and #values as Arrays.

Like a standard Command, a MapCommand can be defined either by passing a block to the constructor, or by defining a subclass of MapCommand and implementing the #process method. If the given block or the #process method accepts more than one argument, the enumerable item is destructured using the splat operator (*); this enables using a MapCommand to map over the keys and values of a Hash. This is the same behavior seen when passing a block with multiple arguments to a native #each method.

If a MapCommand is initialized with the :allow_partial keyword, the ResultList will be passing as long as there is at least one passing Result (or if the MapCommand is called with an empty Enumerable). See ResultList#allow_partial? for details.

Examples:

A MapCommand with a block

titleize_command = Cuprum::MapCommand.new do |str|
  if str.nil? || str.empty?
    next failure(Cuprum::Error.new(message: "can't be blank"))
  end

  str.split(' ').map(&:capitalize).join(' ')
end

A MapCommand Subclass

class TitleizeCommand < Cuprum::MapCommand
  private

  def process(str)
    if str.nil? || str.empty?
      return failure(Cuprum::Error.new(message: "can't be blank"))
    end

    str.split(' ').map(&:capitalize).join(' ')
  end
end

titleize_command = TitleizeCommand.new

With an Array with passing Results

results = titleize_command.call(['hello world', 'greetings programs'])
results.class
#=> Cuprum::ResultsList
results.status
#=> :success
results.value
#=> ['Hello World', 'Greetings Programs']
results.values
#=> ['Hello World', 'Greetings Programs']
results.error
#=> nil
results.errors
#=> [nil, nil]

With an Array with failing Results

results = titleize_command.call([nil, ''])
results.status
#=> :failure
results.value
#=> [nil, nil]
results.values
#=> [nil, nil]
results.error.class
#=> Cuprum::Errors::MultipleErrors
results.errors.map(&:class)
#=> [Cuprum::Error, Cuprum::Error]
results.errors.first.message
#=> "can't be blank"

With an Array with mixed passing and failing Results

results = titleize_command.call([nil, 'greetings programs'])
results.status
#=> :failure
results.value
#=> [nil, "Greetings Programs"]
results.values
#=> [nil, "Greetings Programs"]
results.error.class
#=> Cuprum::Errors::MultipleErrors
results.errors.map(&:class)
#=> [Cuprum::Error, nil]
results.errors.first.message
#=> "can't be blank"

With an Empty Array

results = titleize_command.call([])
results.status
#=> :success
results.value
#=> []
results.values
#=> []
results.error
#=> nil
results.errors
#=> []

With a Hash

inspect_command = Cuprum::MapCommand.new do |key, value|
  "#{key.inspect} => #{value.inspect}"
end

results = inspect_command.call({ ichi: 1, "ni" => 2 })
results.status
#=> :success
results.value
#=> [':ichi => 1', '"ni" => 2']
results.values
#=> [':ichi => 1', '"ni" => 2']
results.error
#=> nil
results.errors
#=> [nil, nil]

With an Enumerable

square_command = Cuprum::MapCommand.new { |i| i ** 2 }

results = square_command.call(0...4)
results.status
#=> :success
results.value
#=> [0, 1, 4, 9]
results.values
#=> [0, 1, 4, 9]

With allow_partial: true

maybe_upcase_command = Cuprum::MapCommand.new do |str|
  next str.upcase if str.is_a?(String)

  failure(Cuprum::Error.new(message: 'not a String'))
end

results = maybe_upcase_command.call([nil, 'greetings', 'programs'])
results.status
#=> :success
results.value
#=> [nil, 'GREETINGS', 'PROGRAMS']
results.values
#=> [nil, 'GREETINGS', 'PROGRAMS']
results.error.class
#=> Cuprum::Errors::MultipleErrors
results.errors.map(&:class)
#=> [Cuprum::Error, nil, nil]
results.errors.first.message
#=> 'not a String'

See Also:

Instance Method Summary collapse

Methods inherited from Command

#to_proc

Methods included from Steps

#step, #steps

Methods included from Currying

#curry

Methods included from Processing

#arity, #process

Constructor Details

#initialize(allow_partial: false) ⇒ MapCommand #initialize(allow_partial: false) {|item| ... } ⇒ MapCommand #initialize(allow_partial: false) {|key, value| ... } ⇒ MapCommand

Returns a new instance of MapCommand.

Overloads:

  • #initialize(allow_partial: false) ⇒ MapCommand

    Parameters:

    • allow_partial (true, false) (defaults to: false)

      If true, allows for some failing results as long as there is at least one passing result. Defaults to false.

  • #initialize(allow_partial: false) {|item| ... } ⇒ MapCommand

    Parameters:

    • allow_partial (true, false) (defaults to: false)

      If true, allows for some failing results as long as there is at least one passing result. Defaults to false.

    Yields:

    • The command implementation, to be called with each successive item in the given enumerable. This overrides the #process method, if any.

    Yield Parameters:

    • item (Object)

      Each item in the given Enumerable.

  • #initialize(allow_partial: false) {|key, value| ... } ⇒ MapCommand

    Parameters:

    • allow_partial (true, false) (defaults to: false)

      If true, allows for some failing results as long as there is at least one passing result. Defaults to false.

    Yields:

    • The command implementation, to be called with each successive item in the given enumerable. This overrides the #process method, if any.

    Yield Parameters:

    • key (Object)

      Each key in the given Hash.

    • value (Object)

      Each value in the given Hash.



191
192
193
194
195
# File 'lib/cuprum/map_command.rb', line 191

def initialize(allow_partial: false, &implementation)
  super(&implementation)

  @allow_partial = allow_partial
end

Instance Method Details

#allow_partial?true, false

Returns if true, allows for some failing results as long as there is at least one passing result. Defaults to false.

Returns:

  • (true, false)

    if true, allows for some failing results as long as there is at least one passing result. Defaults to false.



199
200
201
# File 'lib/cuprum/map_command.rb', line 199

def allow_partial?
  @allow_partial
end

#call(enumerable) ⇒ Cuprum::ResultList

Calls the command implementation for each item in the given Enumerable.

Parameters:

  • enumerable (Array, Hash, Enumerable)

    The collection or enumerable object to map.

Returns:



209
210
211
212
213
# File 'lib/cuprum/map_command.rb', line 209

def call(enumerable)
  build_result_list(
    enumerable.map { |item| splat_items? ? super(*item) : super(item) }
  )
end