Class: Stannum::Contracts::ParametersContract

Inherits:
HashContract show all
Defined in:
lib/stannum/contracts/parameters_contract.rb

Overview

A Parameters defines constraints on the parameters for a block or method.

The ParametersContract requires that the actual object matched be a Hash with the following keys: :arguments, with an Array value; :keywords, with a Hash value; and :block, with a value of either a Proc or nil.

For the arguments constraints, the contract verifies that the correct number of arguments are given and that each argument matches the type or constraint specified. If the contract has a variadic arguments constraint, then each variadic (or “splatted”) argument is checked against the type or constraint.

For the keywords constraints, the contract verifies that the expected keywords are given and that each keyword value matches the type or constraint specified. If the contract has a variadic keywords constraint, then each variadic keyword value is checked against the type or constraint.

For the block constraint, the contract specifies that the block is present, the block is absent, or the block matches the given constraint.

Examples:

Defining A Parameters Contract With Arguments

contract = Stannum::Contracts::ParametersContract.new do
  argument :name, String
  argument :size, String, default: true
end

contract.matches?(
  { arguments: [], keywords: {}, block: nil }
)
#=> false

contract.matches?(
  { arguments: [:a_symbol], keywords: {}, block: nil }
)
#=> false

contract.matches?(
  { arguments: ['Widget', 'Small', :extra], keywords: {}, block: nil }
)
#=> false

contract.matches?(
  { arguments: ['Widget', 'Small', :extra], keywords: {}, block: nil }
)
#=> false

contract.matches?(
  { arguments: ['Widget'], keywords: {}, block: nil }
)
#=> true

contract.matches?(
  { arguments: ['Widget', nil], keywords: {}, block: nil }
)
#=> false

contract.matches?(
  { arguments: ['Widget', 'Small'], keywords: {}, block: nil }
)
#=> true

Defining A Parameters Contract With Keywords

contract = Stannum::Contracts::ParametersContract.new do
  keyword :price,    String
  keyword :quantity, Integer, optional: true
end

contract.matches?(
  { arguments: [], keywords: {}, block: nil }
)
#=> false

contract.matches?(
  arguments: [],
  keywords:  {
    price: 1_000_000,
  },
  block: nil
)
#=> false

contract.matches?(
  arguments: [],
  keywords:  {
    currency: 'USD',
    price:    '$1_000_000',
  },
  block: nil
)
#=> false

contract.matches?(
  arguments: [],
  keywords:  {
    price: '$1_000_000',
  },
  block: nil
)

#=> true
contract.matches?(
  arguments: [],
  keywords:  {
    price:    '$1_000_000',
    quantity: 50,
  },
  block: nil
)
#=> true

Defining A Parameters Contract With Variadic Arguments

contract = Stannum::Contracts::ParametersContract.new do
  arguments :words, String
end

contract.matches?(
  { arguments: [1, 2, 3], keywords: {}, block: nil }
)
#=> false

contract.matches?(
  { arguments: [], keywords: {}, block: nil }
)
#=> true

contract.matches?(
  { arguments: ['foo', 'bar', 'baz'], keywords: {}, block: nil }
)
#=> true

Defining A Parameters Contract With Variadic Keywords

contract = Stannum::Contracts::ParametersContract.new do
  keywords :options, Symbol
end

contract.matches?(
  arguments: [],
  keywords:  {
    price: 1_000_000,
  },
  block: nil
)
#=> false

contract.matches?(
  arguments: [],
  keywords:  {},
  block: nil
)
#=> true

contract.matches?(
  arguments: [],
  keywords:  {
    color: :red,
    shape: :triangle
  },
  block: nil
)
#=> true

Defining A Parameters Contract With A Block Constraint

contract = Stannum::Contracts::ParametersContract.new do
  block true
end

contract.matches?(
  { arguments: [], keywords: {}, block: nil }
)
#=> false

contract.matches?(
  { arguments: [], keywords: {}, block: Proc.new }
)
#=> true

Defined Under Namespace

Classes: Builder

Constant Summary

Constants inherited from Stannum::Constraints::Base

Stannum::Constraints::Base::NEGATED_TYPE, Stannum::Constraints::Base::TYPE

Instance Attribute Summary

Attributes inherited from Stannum::Constraints::Base

#options

Instance Method Summary collapse

Methods inherited from HashContract

#initialize, #key_type, #value_type

Methods inherited from MapContract

#add_key_constraint, #allow_extra_keys?, #expected_keys, #initialize, #with_options

Methods inherited from Stannum::Contract

#add_constraint, #add_property_constraint

Methods inherited from Base

#==, #add_constraint, #concat, #does_not_match?, #each_constraint, #each_pair, #errors_for, #initialize, #match, #matches?, #negated_errors_for, #negated_match

Methods inherited from Stannum::Constraints::Base

#==, #clone, #does_not_match?, #dup, #errors_for, #initialize, #match, #matches?, #message, #negated_errors_for, #negated_match, #negated_message, #negated_type, #type, #with_options

Constructor Details

This class inherits a constructor from Stannum::Contracts::HashContract

Instance Method Details

#add_argument_constraint(index, type, **options) ⇒ Stannum::Contracts::ParametersContract

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.

Parameters:

  • index (Integer, nil)

    The index of the argument. If not given, then the next argument will be constrained with the type.

  • type (Class, Module, Stannum::Constraints:Base)

    The expected type of the argument.

  • options (Hash<Symbol, Object>)

    Configuration options for the constraint. Defaults to an empty Hash.

Returns:



398
399
400
401
402
# File 'lib/stannum/contracts/parameters_contract.rb', line 398

def add_argument_constraint(index, type, **options)
  arguments_contract.add_argument_constraint(index, type, **options)

  self
end

#add_keyword_constraint(keyword, type, **options) ⇒ Stannum::Contracts::ParametersContract

Adds a keyword constraint to the contract.

Generates a keyword 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 given keyword. 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 keyword.

Parameters:

  • keyword (Symbol)

    The keyword to constrain.

  • type (Class, Module, Stannum::Constraints:Base)

    The expected type of the argument.

  • options (Hash<Symbol, Object>)

    Configuration options for the constraint. Defaults to an empty Hash.

Returns:



419
420
421
422
423
# File 'lib/stannum/contracts/parameters_contract.rb', line 419

def add_keyword_constraint(keyword, type, **options)
  keywords_contract.add_keyword_constraint(keyword, type, **options)

  self
end

#set_arguments_item_constraint(name, type) ⇒ Stannum::Contracts::ParametersContract

Sets the variadic arguments constraint for the contract.

If the parameters includes variadic (or “splatted”) arguments, then each item in the variadic arguments array must match the given type or constraint. If the type is a constraint, then the given constraint will be copied with the given options. If the type is a Class or a Module, then a Stannum::Constraints::Type constraint will be created with the given type.

Parameters:

  • name (String, Symbol)

    a human-readable name for the variadic arguments; used in generating error messages.

  • type (Class, Module, Stannum::Constraints:Base)

    The expected type of the variadic arguments items.

Returns:

Raises:

  • (RuntimeError)

    if there is already a variadic arguments constraint defined for the contract.



442
443
444
445
446
# File 'lib/stannum/contracts/parameters_contract.rb', line 442

def set_arguments_item_constraint(name, type)
  arguments_contract.set_variadic_item_constraint(type, as: name)

  self
end

#set_block_constraint(present) ⇒ Stannum::Contracts::ParametersContract

Sets the block parameter constraint for the contract.

If the expected presence is true, a block must be given as part of the parameters. If the expected presence is false, a block must not be given. If the presence is a constraint, then the block must match the constraint.

Parameters:

Returns:

Raises:

  • (RuntimeError)

    if there is already a block constraint defined for the contract.



461
462
463
464
465
466
467
# File 'lib/stannum/contracts/parameters_contract.rb', line 461

def set_block_constraint(present) # rubocop:disable Naming/AccessorMethodName
  raise 'block constraint is already set' if @block_constraint

  @block_constraint = build_block_constraint(present)

  add_key_constraint(:block, @block_constraint)
end

#set_keywords_value_constraint(name, type) ⇒ Stannum::Contracts::ParametersContract

Sets the variadic keywords constraint for the contract.

If the parameters includes variadic (or “splatted”) keywords, then each value in the variadic keywords hash must match the given type or constraint. If the type is a constraint, then the given constraint will be copied with the given options. If the type is a Class or a Module, then a Stannum::Constraints::Type constraint will be created with the given type.

Parameters:

  • name (String, Symbol)

    a human-readable name for the variadic keywords; used in generating error messages.

  • type (Class, Module, Stannum::Constraints:Base)

    The expected type of the variadic keywords values.

Returns:

Raises:

  • (RuntimeError)

    if there is already a variadic keywords constraint defined for the contract.



486
487
488
489
490
# File 'lib/stannum/contracts/parameters_contract.rb', line 486

def set_keywords_value_constraint(name, type)
  keywords_contract.set_variadic_value_constraint(type, as: name)

  self
end