class Contract

This is the main Contract class. When you write a new contract, you'll write it as:

Contract [contract names] => return_value

This class also provides useful callbacks and a validation method.

Attributes

args_contracts[R]
args_validators[R]
klass[R]
method[R]
ret_contract[R]
ret_validator[R]

Public Class Methods

new(klass, method, *contracts) click to toggle source
# File lib/contracts/contract.rb, line 24
def initialize(klass, method, *contracts)
  contracts = correct_ret_only_contract(contracts, method)

  # internally we just convert that return value syntax back to an array
  @args_contracts = contracts[0, contracts.size - 1] + contracts[-1].keys
  @ret_contract   = contracts[-1].values[0]

  determine_has_proc_contract!
  determine_has_options_contract!

  @pattern_match = false
  @klass         = klass
  @method        = method
end
valid?(arg, contract) click to toggle source

Used to verify if an argument satisfies a contract.

Takes: an argument and a contract.

Returns: a tuple: [Boolean, metadata]. The boolean indicates whether the contract was valid or not. If it wasn't, metadata contains some useful information about the failure.

# File lib/contracts/contract.rb, line 19
def self.valid?(arg, contract)
  make_validator(contract)[arg]
end

Public Instance Methods

[](*args, &blk) click to toggle source
# File lib/contracts/contract.rb, line 43
def [](*args, &blk)
  call(*args, &blk)
end
call(*args, &blk) click to toggle source
# File lib/contracts/contract.rb, line 47
def call(*args, &blk)
  call_with(nil, *args, &blk)
end
failure_exception() click to toggle source

Used to determine type of failure exception this contract should raise in case of failure

# File lib/contracts/contract.rb, line 62
def failure_exception
  return PatternMatchingError if pattern_match?
  ParamContractError
end
pattern_match!() click to toggle source

mark contract as pattern matching contract

# File lib/contracts/contract.rb, line 52
def pattern_match!
  @pattern_match = true
end
pattern_match?() click to toggle source

Used to determine if contract is a pattern matching contract

# File lib/contracts/contract.rb, line 57
def pattern_match?
  @pattern_match
end
to_s() click to toggle source
# File lib/contracts/contract.rb, line 39
def to_s
  "#{args_contracts_to_s} => #{ret_contract_to_s}".gsub!("Contracts::Builtin::", "")
end

Private Instance Methods

args_contracts_to_s() click to toggle source
# File lib/contracts/contract.rb, line 112
def args_contracts_to_s
  args_contracts.map { |c| pretty_contract(c) }.join(", ")
end
correct_ret_only_contract(contracts, method) click to toggle source

BEFORE

Contracts::Builtin::Num

AFTER:

{nil=>Contracts::Builtin::Num}
# File lib/contracts/contract.rb, line 73
def correct_ret_only_contract(contracts, method)
  unless contracts.last.is_a?(Hash)
    unless contracts.one?
      raise %{
        It looks like your contract for #{method.name} doesn't have a return
        value. A contract should be written as `Contract arg1, arg2 =>
        return_value`.
      }.strip
    end
    contracts = [nil => contracts[-1]]
  end
  contracts
end
determine_has_options_contract!() click to toggle source
# File lib/contracts/contract.rb, line 107
def determine_has_options_contract!
  relevant_contract     = (@has_proc_contract ? args_contracts[-2] : args_contracts[-1])
  @has_options_contract = kinda_hash?(relevant_contract)
end
determine_has_proc_contract!() click to toggle source
# File lib/contracts/contract.rb, line 103
def determine_has_proc_contract!
  @has_proc_contract = kinda_proc?(args_contracts.last)
end
kinda_hash?(v) click to toggle source
# File lib/contracts/contract.rb, line 125
def kinda_hash?(v)
  v.is_a?(Hash) || v.is_a?(Contracts::Builtin::KeywordArgs)
end
kinda_proc?(v) click to toggle source
# File lib/contracts/contract.rb, line 129
def kinda_proc?(v)
  is_a_proc        = v.is_a?(Class) && (v <= Proc || v <= Method)
  maybe_a_proc     = v.is_a?(Contracts::Maybe) && v.include_proc?
  is_func_contract = v.is_a?(Contracts::Func)

  (is_a_proc || maybe_a_proc || is_func_contract)
end
pretty_contract(c) click to toggle source
# File lib/contracts/contract.rb, line 120
def pretty_contract(c)
  return c.name if c.is_a?(Class)
  c.class.name
end
ret_contract_to_s() click to toggle source
# File lib/contracts/contract.rb, line 116
def ret_contract_to_s
  pretty_contract(ret_contract)
end
splat_args_contract_index() click to toggle source
# File lib/contracts/contract.rb, line 87
def splat_args_contract_index
  @splat_args_contract_index ||= args_contracts.index do |contract|
    contract.is_a?(Contracts::SplatArgs)
  end
end