Class: Contracts::ContractBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/contracts.rb

Instance Method Summary collapse

Constructor Details

#initialize(contract) ⇒ ContractBuilder

Returns a new instance of ContractBuilder.



351
# File 'lib/contracts.rb', line 351

def initialize(contract) = @contract = contract

Instance Method Details

#changes(*attributes) ⇒ Object



367
368
369
370
371
372
373
374
375
376
# File 'lib/contracts.rb', line 367

def changes(*attributes)
  validate_mutation_mode!(:changes)
  observe(*attributes.reject do |attribute|
    @contract.observed.any? do |item|
      item.name == attribute.to_sym
    end
  end)
  @contract.instance_variable_set(:@mutation_policy, :changes)
  @contract.permitted_changes = attributes
end

#ensures(description = "postcondition", &block) ⇒ Object



355
# File 'lib/contracts.rb', line 355

def ensures(description = "postcondition", &block) = add(@contract.postconditions, description, block)

#example(**value) ⇒ Object



409
# File 'lib/contracts.rb', line 409

def example(**value) = @contract.examples << value.freeze

#must_change(*attributes, from: nil, to: nil) ⇒ Object



388
389
390
391
392
393
394
395
396
397
398
# File 'lib/contracts.rb', line 388

def must_change(*attributes, from: nil, to: nil)
  # Retain range constraints for the public DSL; enforcement is intentionally deferred.
  validate_mutation_mode!(:must_change)
  @contract.instance_variable_set(:@required_change_bounds, { attributes: attributes.map(&:to_sym), from: from, to: to }.freeze)
  observe(*attributes.reject do |attribute|
    @contract.observed.any? do |item|
      item.name == attribute.to_sym
    end
  end)
  @contract.required_changes.concat(attributes.map(&:to_sym)).uniq!
end

#observe(*attributes, deep: false, compare_with: nil, &reader) ⇒ Object



378
379
380
381
382
383
384
385
386
# File 'lib/contracts.rb', line 378

def observe(*attributes, deep: false, compare_with: nil, &reader)
  attributes.each do |attribute|
    existing = @contract.observed.find { |item| item.name == attribute.to_sym }
    raise DefinitionError, "duplicate observation for #{attribute}" if existing

    @contract.observed << Observation.new(name: attribute.to_sym, reader: reader, deep: deep,
                                          compare_with: compare_with)
  end
end

#on_raise(type, &block) ⇒ Object



365
# File 'lib/contracts.rb', line 365

def on_raise(type, &block) = @contract.allowed_exceptions << ExceptionRule.new(type: type, handler: block)

#params(**items) ⇒ Object



352
# File 'lib/contracts.rb', line 352

def params(**items) = @contract.parameters = items

#positional(*items) ⇒ Object



353
# File 'lib/contracts.rb', line 353

def positional(*items) = @contract.positionals = items

#pure(scope: :receiver) ⇒ Object Also known as: changes_nothing

Raises:



400
401
402
403
404
405
# File 'lib/contracts.rb', line 400

def pure(scope: :receiver)
  raise DefinitionError, "unsupported purity scope #{scope.inspect}" unless %i[receiver observed].include?(scope)

  validate_mutation_mode!(:pure)
  @contract.instance_variable_set(:@mutation_policy, :pure)
end

#raises(*types, &block) ⇒ Object



359
360
361
362
363
# File 'lib/contracts.rb', line 359

def raises(*types, &block)
  types.each do |type|
    @contract.allowed_exceptions << ExceptionRule.new(type: type, condition: block)
  end
end

#requires(description = "precondition", &block) ⇒ Object



354
# File 'lib/contracts.rb', line 354

def requires(description = "precondition", &block) = add(@contract.preconditions, description, block)

#returns(constraint) ⇒ Object



356
# File 'lib/contracts.rb', line 356

def returns(constraint) = @contract.return_constraint = constraint

#returns!(constraint) ⇒ Object



357
# File 'lib/contracts.rb', line 357

def returns!(constraint) = @contract.return_constraint = Constraints::Predicate.new("non-nil #{Constraints.coerce(constraint).description}") { |v| !v.nil? && Constraints.coerce(constraint).matches?(v) }

#snapshot(&block) ⇒ Object



407
# File 'lib/contracts.rb', line 407

def snapshot(&block) = @contract.instance_variable_set(:@snapshot_block, block)

#unchanged_on_raise(*types) ⇒ Object



408
# File 'lib/contracts.rb', line 408

def unchanged_on_raise(*types) = @contract.unchanged_on_raise_types.concat(types.empty? ? [StandardError] : types).uniq!