Я считаю, что было бы лучше использовать саморекурсивный метод. Таким образом, он идет так глубоко, как необходимо. Это удалит пару ключ-значение, если значение равно нулю или пустой хэш.
class Hash
def compact
delete_if {|k,v| v.is_a?(Hash) ? v.compact.empty? : v.nil? }
end
end
Тогда его использование будет выглядеть так:
x = {:a=>{:b=>2, :c=>3}, :d=>nil, :e=>{:f=>nil}, :g=>{}}
# => {:a=>{:b=>2, :c=>3}, :d=>nil, :e=>{:f=>nil}, :g=>{}}
x.compact
# => {:a=>{:b=>2, :c=>3}}
Для хранения пустых хешей вы можете упростить это до.
class Hash
def compact
delete_if {|k,v| v.compact if v.is_a?(Hash); v.nil? }
end
end