class Flows::Contract::Tuple

Makes a contract fixed size array.

Underlying contracts' transformations are applied.

@example

name_age = Flows::Contract::Tuple.new(String, Integer)

name_age === ['Roman', 29]
# => true

name_age === [10, 20]
# => false

Constants

ARRAY_CONTRACT

Public Class Methods

new(*contracts) click to toggle source

@param contracts [Array<Contract, Object>] contract list. {CaseEq} applied to non-contract values.

# File lib/flows/contract/tuple.rb, line 19
def initialize(*contracts)
  @contracts = contracts.map(&method(:to_contract))
end

Public Instance Methods

check!(other) click to toggle source

@see Contract#check!

# File lib/flows/contract/tuple.rb, line 24
def check!(other)
  ARRAY_CONTRACT.check!(other)
  check_length(other)

  errors = collect_errors(other)
  return true if errors.empty?

  raise Error.new(other, render_errors(other, errors))
end
transform!(other) click to toggle source

@see Contract#transform!

# File lib/flows/contract/tuple.rb, line 35
def transform!(other)
  check!(other)

  other.map.with_index do |elem, index|
    @contracts[index].transform!(elem)
  end
end

Private Instance Methods

check_length(other) click to toggle source
# File lib/flows/contract/tuple.rb, line 45
def check_length(other)
  return if other.length == @contracts.length

  raise Error.new(other, "array length mismatch: must be #{@contracts.length}, got #{other.length}")
end
collect_errors(other) click to toggle source
# File lib/flows/contract/tuple.rb, line 51
def collect_errors(other)
  other.each_with_object({}).with_index do |(elem, errors), index|
    result = @contracts[index].check(elem)

    errors[index] = result.error if result.err?
  end
end
render_errors(other, errors) click to toggle source
# File lib/flows/contract/tuple.rb, line 59
def render_errors(other, errors)
  errors.map do |index, err|
    elem = other[index]
    merge_nested_errors(
      "array element `#{elem.inspect}` with index #{index} is invalid:",
      err
    )
  end.join("\n")
end