I've tried something similar, e.g.
2.0.0-p195 :092 > class Hash
2.0.0-p195 :093?> def delete_values! target
2.0.0-p195 :094?> delete_if { |k, v| v == target }
2.0.0-p195 :095?> each_value { |v| v.delete_values!(target) if v.is_a?(Hash) }
2.0.0-p195 :096?> end
2.0.0-p195 :097?> end
Works ok:
2.0.0-p195 :098 > { a: 1, b: 2, c: 3 }.delete_values! 2
=> {:a=>1, :c=>3}
Also works:
2.0.0-p195 :101 > { a: 1, b: 2, c: { d: {}, e: 5 } }.delete_values!({})
=> {:a=>1, :b=>2, :c=>{:e=>5}}
Note that this approach won't delete an empty hash if you should make an empty hash further down in the structure--if you had a hash containing only empty hashes--you need to switch the order of the recursion and deletion, e.g.
2.0.0-p195 :092 > class Hash
2.0.0-p195 :093?> def delete_values! target
2.0.0-p195 :094?> each_value { |v| v.delete_values!(target) if v.is_a?(Hash) }
2.0.0-p195 :095?> delete_if { |k, v| v == target }
2.0.0-p195 :096?> end
2.0.0-p195 :097?> end