class BloodContracts::Core::Or

Meta refinement type, represents sum of several refinement types

Attributes

sum_of[R]

Represents list of types in the sum

@return [Array<Refined>]

Public Class Methods

inherited(new_klass) click to toggle source

Inheritance handler:

  • adds current sum_of to child

  • sets default value for failure_klass

# File lib/blood_contracts/core/sum.rb, line 70
def inherited(new_klass)
  new_klass.instance_variable_set(:@sum_of, sum_of)
  new_klass.failure_klass ||= SumContractFailure
  super
end
inspect() click to toggle source
Calls superclass method
# File lib/blood_contracts/core/sum.rb, line 26
def inspect; super; end
new(*args) click to toggle source

Metaprogramming around constructor Turns input into Sum meta-class

@param (see initialze)

rubocop:disable Style/SingleLineMethods

Calls superclass method BloodContracts::Core::Refined::new
# File lib/blood_contracts/core/sum.rb, line 19
def new(*args)
  return super(*args) if @finalized

  new_sum = args.reduce([]) do |acc, type|
    type.respond_to?(:sum_of) ? acc + type.sum_of.to_a : acc << type
  end

  sum = Class.new(self) { def inspect; super; end }
  finalize!(sum, new_sum)
  sum
end
or_a(other_type) click to toggle source

Compose types in a Sum check Sum passes data from type to type in parallel, only one type have to match

@return [BC::Sum]

# File lib/blood_contracts/core/sum.rb, line 37
def or_a(other_type)
  sum = Class.new(self) { def inspect; super; end }
  new_sum = sum_of.to_a
  if other_type.respond_to?(:sum_of)
    new_sum += other_type.sum_of.to_a
  else
    new_sum << other_type
  end
  finalize!(sum, new_sum)
  sum
end
Also aliased as: or_an, |
or_an(other_type)

rubocop:enable Style/SingleLineMethods

Alias for: or_a
|(other_type)
Alias for: or_a

Private Class Methods

finalize!(new_class, new_sum) click to toggle source

@private

# File lib/blood_contracts/core/sum.rb, line 53
        def finalize!(new_class, new_sum)
  new_class.instance_variable_set(:@sum_of, ::Set.new(new_sum.compact))
  new_class.instance_variable_set(:@finalized, true)
end

Public Instance Methods

errors() click to toggle source

List of errors per type during the matching

@return [Array<Hash<Refined, String>>]

# File lib/blood_contracts/core/sum.rb, line 98
def errors
  @context[:errors]
end
match() click to toggle source

The type which is the result of data matching process For Tuple it verifies that all the attributes data are valid types

@return [BC::Refined]

# File lib/blood_contracts/core/sum.rb, line 82
def match
  @or_matches = self.class.sum_of.map do |type|
    type.match(@value, context: @context.dup)
  end

  if (match = @or_matches.find(&:valid?))
    match
  else
    @or_matches.dup.unshift(failure).reduce(:merge!)
  end
end

Private Instance Methods

failure(*) click to toggle source

Helper to build a ContractFailure with shared context

@return [ContractFailure]

# File lib/blood_contracts/core/sum.rb, line 106
        def failure(*)
  sum_context = @or_matches.map(&:context)
  @context[:sum_failure_contexts] = sum_context
  self.class.failure_klass.new(context: @context)
end
inspect() click to toggle source

@private

# File lib/blood_contracts/core/sum.rb, line 113
        def inspect
  "#<sum #{self.class.name} is #{self.class.sum_of.to_a.join(' or ')}"\
  " (value=#{@value})>"
end