Class: BloodContracts::Core::Pipe

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

Overview

Meta refinement type, represents pipe 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

===, call, inherited, #invalid?, match, or_a, #unpack, #valid?

Constructor Details

#initializePipe

Constructs a Pipe using the given value (for Pipe steps are also stored in the context)



80
81
82
83
84
# File 'lib/blood_contracts/core/pipe.rb', line 80

def initialize(*)
  super
  @context[:steps] = @context[:steps].to_a
  @context[:steps_values] = {}
end

Class Attribute Details

.namesArray<Symbol> (readonly)

List of data transformation step names

Returns:

  • (Array<Symbol>)


15
16
17
# File 'lib/blood_contracts/core/pipe.rb', line 15

def names
  @names
end

.stepsArray<Refined> (readonly)

List of data transformation step

Returns:



9
10
11
# File 'lib/blood_contracts/core/pipe.rb', line 9

def steps
  @steps
end

Class Method Details

.and_then(other_type, **kwargs) ⇒ BC::Pipe Also known as: >

Compose types in a Pipe check Pipe passes data from type to type sequentially

rubocop:disable Style/CaseEquality

Returns:

Raises:

  • (ArgumentError)


36
37
38
39
40
41
# File 'lib/blood_contracts/core/pipe.rb', line 36

def and_then(other_type, **kwargs)
  raise ArgumentError unless Class === other_type
  pipe = Class.new(self) { def inspect; super; end }
  finalize!(pipe, [self, other_type], kwargs[:names].to_a)
  pipe
end

.inspectString

Returns text representation of Pipe meta-class

Returns:

  • (String)


63
64
65
66
# File 'lib/blood_contracts/core/pipe.rb', line 63

def inspect
  return super if name
  "Pipe(#{steps.to_a.join(',')})"
end

.new(*args, **kwargs, &block) ⇒ Object

rubocop:disable Style/SingleLineMethods

Raises:

  • (ArgumentError)


18
19
20
21
22
23
24
25
26
27
28
# File 'lib/blood_contracts/core/pipe.rb', line 18

def new(*args, **kwargs, &block)
  return super(*args, **kwargs) if @finalized
  names = kwargs.delete(:names) unless kwargs.empty?
  names ||= []

  raise ArgumentError unless args.all? { |type| type < Refined }
  pipe = Class.new(self) { def inspect; super; end }
  finalize!(pipe, args, names)
  pipe.class_eval(&block) if block_given?
  pipe
end

.step(name, type) ⇒ Object

Helper which registers step in validation pipe, also defines a reader

Parameters:

  • name (Symbol)

    of the matching step

  • type (Refined)

    of the matching step

Raises:

  • (ArgumentError)


50
51
52
53
54
55
56
57
# File 'lib/blood_contracts/core/pipe.rb', line 50

def step(name, type)
  raise ArgumentError unless type < Refined
  @steps << type
  @names << name
  define_method(name) do
    match.context.dig(:steps_values, name)
  end
end

Instance Method Details

#errorsArray<Hash<Refined, String>>

List of errors per type during the matching

Returns:



108
109
110
# File 'lib/blood_contracts/core/pipe.rb', line 108

def errors
  @context[:errors]
end

#matchBC::Refined

The type which is the result of data matching process For PIpe it verifies that data is valid through all data transformation steps

Returns:



92
93
94
95
96
97
98
99
100
101
102
# File 'lib/blood_contracts/core/pipe.rb', line 92

def match
  steps_enumerator.reduce(value) do |next_value, (step, index)|
    match = next_step_value_match!(step, next_value, index)

    break match if match.invalid?
    next match unless block_given?
    next refine_value(yield(match)) if index < self.class.steps.size - 1

    match
  end
end