Extract hash in Ruby on Rails

Asked

Viewed 289 times

1

I got the following Hash

my_hash = {city: {id:1, created_at: '', name: 'test_city'}, 
           uf: {id:1, created_at: '', name: 'test_uf'}}

I need to extract some data from it ex:

my_hash.extract!({city: [:id, :name], uf: [:id, :name]})

Expected return:

{city: {id:1, name: 'test_city'}, uf: {id:1, name: 'test_uf'}}

Because it doesn’t work, what’s the best way to do this?

  • Extract will modify the original hash and return you another hash, that’s what you want to do, or you just want to access the values?

  • What do you expect in return? Give an example.

  • I edited the question with the expected values.

1 answer

0


There is an extension on 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 class method 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 the way you suggested.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.