There is an extension in ActiveSupport
that allows you to extract keys from a Hash
:
my_hash = {
city: {
id: 1,
created_at: '',
name: 'test_city'
},
uf: {
id: 1,
created_at: '',
name: 'test_uf'
}
}
my_hash[:city].slice(:id, :name) #=> { id: 1, name: 'test_city' }
It's not quite the behavior you want, but it can be used to solve your problem as follows:
Hash[my_hash.slice(:city, :uf). { |k, v| [k, v.slice(:id, :name) }]
This behavior could be generalized and encapsulated in a method of class Hash
as follows - as available in makandra cards :
Hash.class_eval do
def deep_slice(*allowed_keys)
sliced = {}
allowed_keys.each do |allowed_key|
if allowed_key.is_a?(Hash)
allowed_key.each do |allowed_subkey, allowed_subkey_values|
if has_key?(allowed_subkey)
value = self[allowed_subkey]
if value.is_a?(Hash)
sliced[allowed_subkey] = value.deep_slice(*Array.wrap(allowed_subkey_values))
else
raise ArgumentError, "can only deep-slice hash values, but value for #{allowed_subkey.inspect} was of type #{value.class.name}"
end
end
end
else
if has_key?(allowed_key)
sliced[allowed_key] = self[allowed_key]
end
end
end
sliced
end
end
So this method could be used in the way you suggested.