Module: Katachi::Comparator

Defined in:
lib/katachi/comparator.rb,
lib/katachi/comparator/compare_kv.rb,
lib/katachi/comparator/compare_hash.rb,
lib/katachi/comparator/compare_array.rb

Overview

Katachi::Comparator.compare_array is the main entry point for comparing array. It is called by Katachi::Comparator.compare and should not be called directly. It returns a Katachi::ComparisonResult object.

Class Method Summary collapse

Class Method Details

.compare(value:, shape:) ⇒ Katachi::ComparisonResult

The main method for comparing a value against a shape Most of the logic is delegated to the other methods within this module In order to handle nested arrays and hashes the comparison methods are often recursive.

Parameters:

  • value (Object) —

    The value to compare

  • shape (Object) —

    The shape to compare against

Returns:



17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/katachi/comparator.rb', line 17

def self.compare(value:, shape:)
  retrieved_shape = Katachi::Shapes[shape]
  return retrieved_shape.kt_compare(value) if retrieved_shape.respond_to?(:kt_compare)
  return compare_equalities(value:, shape: retrieved_shape) if retrieved_shape.is_a?(Proc)
  return object_class_universal_match(value:) if retrieved_shape == Object

  case value
  when Array then compare_array(value:, shape: retrieved_shape)
  when Hash then compare_hash(value:, shape: retrieved_shape)
  else compare_equalities(value:, shape: retrieved_shape)
  end
end

.compare_array(value:, shape:) ⇒ Katachi::ComparisonResult

Compare a value that is an array against a shape This method is called by Katachi::Comparator.compare and should not be called directly. It is not private so that it can be tested directly.

Parameters:

  • value (Array) —

    the value to compare

  • shape (Object) —

    the shape to compare against

Returns:



14
15
16
17
18
19
20
21
22
23
# File 'lib/katachi/comparator/compare_array.rb', line 14

def self.compare_array(value:, shape:)
  failure = precompare_array(value:, shape:)
  return failure if failure

  child_results = compare_array_elements(array: value, shape:)
  # All array elements must be valid against at least one sub_shape
  is_match = child_results.values.all?(&:match?)
  code = is_match ? :array_is_match : :array_is_mismatch
  Katachi::ComparisonResult.new(value:, shape:, code:, child_results:)
end

.compare_equalities(value:, shape:) ⇒ Katachi::ComparisonResult

The method for comparing two values that are not arrays or hashes It relies on the case equality operator (===) to do the heavy lifting.

Parameters:

  • value (Object) —

    The value to compare

  • shape (Object) —

    The shape to compare against

Returns:



36
37
38
39
40
41
42
43
# File 'lib/katachi/comparator.rb', line 36

def self.compare_equalities(value:, shape:)
  code = if shape == value then :exact_match
         elsif shape === value then :match # rubocop:disable Style/CaseEquality
         else
           :mismatch
         end
  Katachi::ComparisonResult.new(value:, shape:, code:)
end

.compare_hash(value:, shape:) ⇒ Katachi::ComparisonResult

Compare a value that is a hash against a shape This method is called by Katachi::Comparator.compare and should not be called directly. It is not private so that it can be tested directly.

Parameters:

  • value (Hash) —

    the value to compare

  • shape (Object) —

    the shape to compare against

Returns:



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/katachi/comparator/compare_hash.rb', line 20

def self.compare_hash(value:, shape:)
  failure = precompare_hash(value:, shape:)
  return failure if failure

  child_results = {
    "$required_keys": compare_hash_required_keys(value_keys: value.keys, shape:),
    "$extra_keys": compare_hash_extra_keys(value_keys: value.keys, shape_keys: shape.keys),
    "$values": compare_hash_values(value:, shape:),
  }
  # All categories of checks must pass for the hash to be a match
  code = child_results.values.all?(&:match?) ? :hash_is_match : :hash_is_mismatch
  Katachi::ComparisonResult.new(value:, shape:, code:, child_results:)
end