class YamlSearchDiff

Public Class Methods

new() click to toggle source
# File lib/yaml_search_diff.rb, line 6
def initialize
  @scalar_scanner = Psych::ScalarScanner.new(Psych::ClassLoader.new)
end

Public Instance Methods

run(key:, yml_1:, yml_2:) click to toggle source
# File lib/yaml_search_diff.rb, line 10
def run(key:, yml_1:, yml_2:)
  return "" unless yml_1.is_a?(Hash) && yml_2.is_a?(Hash)

  searched_1 = key.include?(':') ? search_dig(key, yml_1) : search(key, yml_1)
  searched_2 = key.include?(':') ? search_dig(key, yml_2) : search(key, yml_2)

  Diffy::Diff.new(
    YAML.dump(searched_1),
    YAML.dump(searched_2)
  )
end

Private Instance Methods

dfs(hash, key) click to toggle source
# File lib/yaml_search_diff.rb, line 42
def dfs(hash, key)
  keys = hash.keys.sort_by(&:to_s)
  keys.each do |k|
    throw :has_key, hash[k] if k == key
    dfs(hash[k], key) if hash[k].is_a?(Hash)
  end
  {}
end
nested_sort_array(array) click to toggle source
# File lib/yaml_search_diff.rb, line 72
def nested_sort_array(array)
  array.each_with_index do |v, i|
    if v.is_a?(Hash)
      array[i] = nested_sort_hash(v)
    elsif v.is_a?(Array)
      array[i] = nested_sort_array(v)
    end
  end
  array.sort_by(&:to_s)
end
nested_sort_hash(hash) click to toggle source
# File lib/yaml_search_diff.rb, line 61
def nested_sort_hash(hash)
  hash.each do |k, v|
    if v.is_a?(Hash)
      hash[k] = nested_sort_hash(v)
    elsif v.is_a?(Array)
      hash[k] = nested_sort_array(v)
    end
  end
  hash.sort_by { |k, v| k.to_s }.to_h
end
search_dig(key, yml) click to toggle source
# File lib/yaml_search_diff.rb, line 30
def search_dig(key, yml)
  tokenized_keys = key.split(':').map {|k| @scalar_scanner.tokenize(k) }
  return sort_yml(yml) if tokenized_keys.size.zero?

  first_key = tokenized_keys.first

  searched = catch(:has_key) { dfs(yml, first_key) }
  digged = searched.dig(*tokenized_keys[1..])

  sort_yml(digged)
end
sort_yml(yml) click to toggle source
# File lib/yaml_search_diff.rb, line 51
def sort_yml(yml)
  if yml.is_a?(Hash)
    nested_sort_hash(yml)
  elsif yml.is_a?(Array)
    nested_sort_array(yml)
  else
    yml
  end
end