Class: BloodContracts::Core::Sum

Inherits:
Refined
  • Object
show all
Defined in:
lib/blood_contracts/core/sum.rb

Overview

Meta refinement type, represents sum of several refinement types

Class Attribute Summary collapse

Attributes inherited from Refined

#context

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Refined

===, and_then, call, #initialize, #invalid?, match, #unpack, #valid?

Constructor Details

This class inherits a constructor from BloodContracts::Core::Refined

Class Attribute Details

.sum_ofArray<Refined> (readonly)

Represents list of types in the sum

Returns:



11
12
13
# File 'lib/blood_contracts/core/sum.rb', line 11

def sum_of
  @sum_of
end

Class Method Details

.inherited(new_klass) ⇒ Object

Inheritance handler:

  • adds current sum_of to child

  • sets default value for failure_klass



70
71
72
73
74
# 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

.inspectString

Returns text representation of Sum meta-class

Returns:

  • (String)


62
63
64
65
# File 'lib/blood_contracts/core/sum.rb', line 62

def inspect
  return super if name
  "Sum(#{sum_of.map(&:inspect).join(',')})"
end

.new(*args) ⇒ Object

Metaprogramming around constructor Turns input into Sum meta-class

rubocop:disable Style/SingleLineMethods



19
20
21
22
23
24
25
26
27
28
29
# 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) ⇒ BC::Sum Also known as: or_an, |

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

Returns:



37
38
39
40
41
42
43
44
45
46
47
# 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

Instance Method Details

#errorsArray<Hash<Refined, String>>

List of errors per type during the matching

Returns:



98
99
100
# File 'lib/blood_contracts/core/sum.rb', line 98

def errors
  @context[:errors]
end

#matchBC::Refined

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

Returns:



82
83
84
85
86
87
88
89
90
91
92
# 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