Module: RSpec::JsonApi::Traversal

Defined in:
lib/rspec/json_api/traversal.rb

Overview

Traversal holds the structural helpers used to compare JSON shapes: collecting the nested key structure of a Hash and sorting it into a canonical order. These were previously monkey-patched onto core Hash and Array; keeping them here means the gem no longer mutates those classes in the host application.

Class Method Summary collapse

Class Method Details

.deep_key_paths(hash) ⇒ Object

Every leaf key path of a hash, e.g. { a: { b: 1 }, c: 2 } => [[:a, :b], [:c]].



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/rspec/json_api/traversal.rb', line 23

def deep_key_paths(hash)
  stack = hash.map { |key, value| [[key], value] }
  key_map = []

  until stack.empty?
    key, value = stack.pop

    key_map << key unless value.is_a?(Hash)

    next unless value.is_a?(Hash)

    value.each { |k, v| stack.push([key.dup << k, v]) }
  end

  key_map.reverse
end

.deep_keys(hash) ⇒ Object

The nested keys of a hash, with each nested hash’s keys inlined as an array, e.g. { a: 1, b: { c: 2 } } => [:a, :b, [:c]].



15
16
17
18
19
20
# File 'lib/rspec/json_api/traversal.rb', line 15

def deep_keys(hash)
  hash.each_with_object([]) do |(key, value), keys|
    keys << key
    keys << deep_keys(value) if value.respond_to?(:keys)
  end
end

.deep_sort(array) ⇒ Object

Recursively sorts an array (and any nested arrays) into a canonical order so two key structures can be compared regardless of original order.



42
43
44
45
46
# File 'lib/rspec/json_api/traversal.rb', line 42

def deep_sort(array)
  array
    .map { |element| element.is_a?(Array) ? deep_sort(element) : element }
    .sort_by { |element| element.is_a?(Array) ? element.first.to_s : element.to_s }
end