class SimpleContracts::Base

Public Class Methods

call(*args, **kwargs) { || ... } click to toggle source
# File lib/simple_contracts/base.rb, line 33
def call(*args, **kwargs)
  new(*args, **kwargs).call { yield }
end
expectations_methods() click to toggle source
# File lib/simple_contracts/base.rb, line 41
def expectations_methods
  @expectations_methods ||= methods_with_prefix("expect_")
end
guarantees_methods() click to toggle source
# File lib/simple_contracts/base.rb, line 37
def guarantees_methods
  @guarantees_methods ||= methods_with_prefix("guarantee_")
end
new(*args, async: nil, logger: nil, sampler: nil, stats: nil, **kwargs) click to toggle source
# File lib/simple_contracts/base.rb, line 57
def initialize(*args, async: nil, logger: nil, sampler: nil, stats: nil, **kwargs)
  @async = async.nil? ? default_async : !!async
  @sampler = sampler
  @stats = stats
  @logger = logger
  @input = {args: args, kwargs: kwargs}
  @meta = {checked: [], input: @input}
end

Private Class Methods

methods_with_prefix(prefix) click to toggle source
# File lib/simple_contracts/base.rb, line 47
def methods_with_prefix(prefix)
  private_instance_methods.
    each_with_object([]) do |method_name, memo|
      method_name = method_name.to_s
      next unless method_name.start_with?(prefix)
      memo << method_name
    end.sort
end

Public Instance Methods

call() { || ... } click to toggle source
# File lib/simple_contracts/base.rb, line 66
def call
  return yield unless enabled?
  @output = yield
  @async ? verify_async : verify
  @output
end
Also aliased as: match!
contract_name() click to toggle source
# File lib/simple_contracts/base.rb, line 83
def contract_name
  self.class.name
end
deserialize(state_dump) click to toggle source
# File lib/simple_contracts/base.rb, line 79
def deserialize(state_dump)
  Marshal.load(state_dump)
end
match!()
Alias for: call
serialize() click to toggle source
# File lib/simple_contracts/base.rb, line 75
def serialize
  Marshal.dump(input: @input, output: @output, meta: @meta)
end

Private Instance Methods

call_matchers() click to toggle source
# File lib/simple_contracts/base.rb, line 97
def call_matchers
  match_guarantees!
  match_expectations!
end
concurrent_options() click to toggle source
# File lib/simple_contracts/base.rb, line 93
def concurrent_options
  {}
end
default_async() click to toggle source
# File lib/simple_contracts/base.rb, line 89
def default_async
  true
end
enabled?() click to toggle source
# File lib/simple_contracts/base.rb, line 160
def enabled?
  ENV["ENABLE_#{self.class.name}"].to_s != 'false'
end
execute_async() { || ... } click to toggle source
# File lib/simple_contracts/base.rb, line 113
def execute_async
  ::Concurrent::Future.
    execute(concurrent_options) { yield }.
    add_observer(self, :observe_errors)
end
keep_meta(rule, error = nil) click to toggle source
# File lib/simple_contracts/base.rb, line 142
def keep_meta(rule, error = nil)
  sample_path = sampler.sample!(rule)
  meta = sample_path ? @meta.merge(sample_path: sample_path) : @meta
  stats.log(rule, meta, error)
end
logger() click to toggle source
# File lib/simple_contracts/base.rb, line 156
def logger
  @logger ||= ::Logger.new(STDOUT)
end
match_expectations!() click to toggle source
# File lib/simple_contracts/base.rb, line 175
def match_expectations!
  methods = self.class.expectations_methods
  return if methods.empty?
  return if methods.any? do |method_name|
    @meta[:checked] << method_name
    next unless !!send(method_name)
    keep_meta(method_name)
    true
  end

  raise ExpectationsError, @meta
end
match_guarantees!() click to toggle source
# File lib/simple_contracts/base.rb, line 164
def match_guarantees!
  methods = self.class.guarantees_methods
  return if methods.empty?
  return if methods.all? do |method_name|
    @meta[:checked] << method_name
    !!send(method_name)
  end

  raise GuaranteesError, @meta
end
observe_errors(_time, _value, reason) click to toggle source
# File lib/simple_contracts/base.rb, line 119
def observe_errors(_time, _value, reason)
  return unless reason

  rule = rule_from_error(reason)
  error = reason if rule == :unexpected_error

  keep_meta(rule, error)
rescue StandardError => error
  logger.error(error)
  raise
end
rule_from_error(error) click to toggle source
# File lib/simple_contracts/base.rb, line 131
def rule_from_error(error)
  case error
  when GuaranteesError
    :guarantee_failure
  when ExpectationsError
    :expectation_failure
  else
    :unexpected_error
  end
end
sampler() click to toggle source
# File lib/simple_contracts/base.rb, line 148
def sampler
  @sampler ||= ::SimpleContracts::Sampler.new(self)
end
stats() click to toggle source
# File lib/simple_contracts/base.rb, line 152
def stats
  @stats ||= ::SimpleContracts::Statistics.new(contract_name, logger: logger)
end
verify() click to toggle source
# File lib/simple_contracts/base.rb, line 102
def verify
  call_matchers
rescue StandardError => error
  observe_errors(Time.now, nil, error)
  raise
end
verify_async() click to toggle source
# File lib/simple_contracts/base.rb, line 109
def verify_async
  execute_async { call_matchers }
end