There are two ruby on rails internationalization yaml files. One file is complete and another one is with missing keys. How can I compare two yaml files and see missing keys in
Assuming file1
is the proper version and file2
is the version with missing keys:
def compare_yaml_hash(cf1, cf2, context = [])
cf1.each do |key, value|
unless cf2.key?(key)
puts "Missing key : #{key} in path #{context.join(".")}"
next
end
value2 = cf2[key]
if (value.class != value2.class)
puts "Key value type mismatch : #{key} in path #{context.join(".")}"
next
end
if value.is_a?(Hash)
compare_yaml_hash(value, value2, (context + [key]))
next
end
if (value != value2)
puts "Key value mismatch : #{key} in path #{context.join(".")}"
end
end
end
Now
compare_yaml_hash(YAML.load_file("file1"), YAML.load_file("file2"))
Limitation: Current implementation should be extended to support arrays if your YAML file contains arrays.
differz compares two YAML files and prints missing keys in the second file.
It comes both as a library and as a command-line tool. You can install the latter with gem install differz
.
I wanted to extract the diff to have something to work with, and the snippet here just prints stuff. So my version returns a hash with diff. It's structure mirrors the original hashes, but the values are descriptions of the differences.
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
I've then used it pretty much as:
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
I couldn't find a fast tool to do that. I decided to write my own tool for this.
You can install it with cabal:
$ cabal update
$ cabal install yamlkeysdiff
Then you can diff two files this way:
$ yamlkeysdiff file1.yml file2.yml
> missing key in file2
< missing key in file1
You can also compare two subsets of the files:
$ yamlkeysdiff "file1.yml#key:subkey" "file2.yml#otherkey"
It behaves exactly like diff
, you can do this:
$ yamlkeysdiff file1.yml file2.yml && echo Is the same || echo Is different