Я хотел извлечь diff, чтобы было с чем работать, а фрагмент здесь просто печатает материал. Так что моя версия возвращает хеш с diff. Его структура отражает исходные хэши, но значения являются описаниями различий.
def deep_hash_diff(hash1, hash2, hash1_name = 'Hash 1', hash2_name = 'Hash 2')
diff = {}
(hash1.keys - hash2.keys).each do |key1|
diff[key1] = "Present in #{hash1_name}, but not in #{hash2_name}"
end
(hash2.keys - hash1.keys).each do |key2|
diff[key2] = "Present in #{hash2_name}, but not in #{hash1_name}"
end
(hash1.keys & hash2.keys).each do |common_key|
if hash1[common_key].is_a?(Hash)
if hash2[common_key].is_a?(Hash)
res = deep_hash_diff(hash1[common_key], hash2[common_key], hash1_name, hash2_name)
diff[common_key] = res if res.present?
else
diff[common_key] = "#{hash1_name} has nested hash, but #{hash2_name} just value #{hash2[common_key]}"
end
elsif hash2[common_key].is_a?(Hash)
diff[common_key] = "#{hash2_name} has nested hash, but #{hash1_name} just value #{hash1[common_key]}"
end
end
diff
end
Я тогда использовал это как:
res = deep_hash_diff(YAML.load_file("en.yml"), YAML.load_file("spa.yml"), 'English translation', 'Spanish translation')
puts(res.to_yaml) # for nicer output