class Stannum::Contracts::Parameters::ArgumentsContract

@api private

An ArgumentsContract constrains the arguments given for a method.

Constants

UNDEFINED

Value used when arguments array does not have a value for the given index.

Attributes

variadic_constraint[R]
variadic_definition[R]

Public Class Methods

new(**options) click to toggle source

@param options [Hash<Symbol, Object>] Configuration options for the

contract. Defaults to an empty Hash.
Calls superclass method Stannum::Contracts::TupleContract::new
# File lib/stannum/contracts/parameters/arguments_contract.rb, line 17
def initialize(**options)
  super(allow_extra_items: false, **options)
end

Public Instance Methods

add_argument_constraint(index, type, default: false, **options) click to toggle source

Adds an argument constraint to the contract.

Generates an argument constraint based on the given type. If the type is a constraint, then the given constraint will be copied with the given options and added for the argument at the index. If the type is a Class or a Module, then a Stannum::Constraints::Type constraint will be created with the given type and options and added for the argument.

If the index is specified, then the constraint will be added for the argument at the specified index. If the index is not given, then the constraint will be applied to the next unconstrained argument. For example, the first argument constraint will be added for the argument at index 0, the second constraint for the argument at index 1, and so on.

@param index [Integer, nil] The index of the argument. If not given, then

the next argument will be constrained with the type.

@param type [Class, Module, Stannum::Constraints:Base] The expected type

of the argument.

@param default [Boolean] If true, the argument has a default value, and

the constraint will ignore arguments with no value at that index.

@param options [Hash<Symbol, Object>] Configuration options for the

constraint. Defaults to an empty Hash.

@return [Stannum::Contracts::Parameters::ArgumentsContract] the contract.

# File lib/stannum/contracts/parameters/arguments_contract.rb, line 45
def add_argument_constraint(index, type, default: false, **options)
  index    ||= next_index
  constraint = Stannum::Support::Coercion.type_constraint(type, **options)

  add_index_constraint(index, constraint, default: !!default, **options)

  self
end
set_variadic_constraint(constraint, as: nil) click to toggle source

Sets a constraint for the variadic arguments.

The given constraint must match the variadic arguments array as a whole. To constraint each individual item, use set_variadic_item_constraint.

@param constraint [Stannum::Constraints::Base] The constraint to add.

The variadic arguments (an array) as a whole must match the given
constraint.

@param as [Symbol] A human-friendly reference for the additional

arguments. Used when generating errors. Should be the same name used in
the method definition.

@return [self] the contract.

@raise [RuntimeError] if the variadic arguments constraint is already set.

@see set_variadic_item_constraint

# File lib/stannum/contracts/parameters/arguments_contract.rb, line 71
def set_variadic_constraint(constraint, as: nil)
  raise 'variadic arguments constraint is already set' if allow_extra_items?

  options[:allow_extra_items] = true

  variadic_constraint.receiver = constraint

  variadic_definition.options[:property_name] = as if as

  self
end
set_variadic_item_constraint(item_type, as: nil) click to toggle source

Sets a constraint for the variadic argument items.

The given type or constraint must individually match each item (if any) in the variadic arguments. To constrain the variadic arguments as a whole, use set_variadic_constraint.

@param item_type [Stannum::Constraints::Base, Class, Module] The type or

constraint to add. If the type is a Class or Module, then it is
converted to a Stannum::Constraints::Type. Each item in the variadic
arguments must match the given constraint.

@param as [Symbol] A human-friendly reference for the additional

arguments. Used when generating errors. Should be the same name used in
the method definition.

@return [self] the contract.

@raise [RuntimeError] if the variadic arguments constraint is already set.

@see set_variadic_constraint

# File lib/stannum/contracts/parameters/arguments_contract.rb, line 102
def set_variadic_item_constraint(item_type, as: nil)
  type       = coerce_item_type(item_type)
  constraint = Stannum::Constraints::Types::ArrayType.new(item_type: type)

  set_variadic_constraint(constraint, as: as)
end

Protected Instance Methods

add_errors_for(definition, value, errors) click to toggle source
Calls superclass method Stannum::Contracts::Base#add_errors_for
# File lib/stannum/contracts/parameters/arguments_contract.rb, line 111
def add_errors_for(definition, value, errors)
  return super unless value == UNDEFINED

  super(definition, nil, errors)
end
add_negated_errors_for(definition, value, errors) click to toggle source
# File lib/stannum/contracts/parameters/arguments_contract.rb, line 117
def add_negated_errors_for(definition, value, errors)
  return super unless value == UNDEFINED

  super(definition, nil, errors)
end
map_value(actual, **options) click to toggle source
# File lib/stannum/contracts/parameters/arguments_contract.rb, line 123
def map_value(actual, **options)
  return super unless options[:property_type] == :index

  return super unless actual.is_a?(Array)

  return super if options[:property] < actual.size

  UNDEFINED
end
match_constraint(definition, value) click to toggle source
# File lib/stannum/contracts/parameters/arguments_contract.rb, line 133
def match_constraint(definition, value)
  return super unless value == UNDEFINED

  definition.options[:default] ? true : super(definition, nil)
end
match_negated_constraint(definition, value) click to toggle source
# File lib/stannum/contracts/parameters/arguments_contract.rb, line 139
def match_negated_constraint(definition, value)
  return super unless value == UNDEFINED

  definition.options[:default] ? false : super(definition, nil)
end

Private Instance Methods

add_extra_items_constraint() click to toggle source
# File lib/stannum/contracts/parameters/arguments_contract.rb, line 151
def add_extra_items_constraint
  count = -> { expected_count }

  @variadic_constraint = Stannum::Constraints::Delegator.new(
    Stannum::Constraints::Parameters::ExtraArguments.new(count)
  )

  add_constraint @variadic_constraint

  @variadic_definition = @constraints.last
end
coerce_item_type(item_type) click to toggle source
# File lib/stannum/contracts/parameters/arguments_contract.rb, line 163
def coerce_item_type(item_type)
  Stannum::Support::Coercion.type_constraint(item_type, as: 'item type')
end
next_index() click to toggle source
# File lib/stannum/contracts/parameters/arguments_contract.rb, line 167
def next_index
  index = -1

  each_constraint do |definition|
    next unless definition.options[:property_type] == :index
    next unless definition.property.is_a?(Integer)

    index = definition.property if definition.property > index
  end

  1 + index
end