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



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



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



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



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



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