![](/assets/img/rosca_maca.jpeg)
Hash With Indifferent Access
Utilizando o Ruby puro nós podemos utilizar uma classe chamada Hash que será responsável por disponibilizar uma estrutura de chave/valor.
hash = Hash.new
hash[:banana] = 123 # chave do tipo symbol
# { banana: 123 }
hash = Hash.new
hash["banana"] = 123 # chave do tipo string
# "{ 'banana' => 123 }"
Porém a chave desse hash pode ser acessada ou criada de
duas maneiras, symbol (:banana)
ou string ("banana")
. Com isso após ter
escolhido o tipo da chave do seu hash ele só poderá ser acessado por um valor
daquele tipo escolhido. Com isso podemos ter alguns erros inesperados ao
utilizar um hash.
Ajuda no Rails
Se você utiliza o framework Rails junto com o Ruby,
existe uma opção para evitar esse problema. O módulo ActiveSupport
possui uma
classe para lidar com essa situação
ActiveSupport::HashWithIndifferentAccess
.
hash = HashWithIndifferentAccess.new(banana: 123)
# ou
hash = Hash.new(banana: 123)
hash.with_indifferent_access
# Dessa forma será possível ler hash[:banana] ou hash['banana']
Nem tudo são flores
Uma coisa que nós sempre encontramos na programação independente da linguagem ou framework são trade-offs. Sempre vamos ouvir que não existe bala de prata para um determinado problema, ao usar uma abordagem nós sempre temos que nos atentar ao lado bom e principalmente ao lado ruim.
Com isso, trazendo para esse caso do Hash, ele não é indicado para ser usado a todo momento, pois por ser mais versátil ele irá consumir mais processamento. Portanto será muito importante analisar o local que o HashWithIndifferentAccess irá habitar e se ele é realmente necessário. Ou se não seria melhor estabelecer um padrão de hash recebido por aquela classe.
Benchmark
Para não ficar muito abstrato, vou deixar o trecho de
código que utilizei para fazer esse estudo entre Hash
e
HashWithIndifferentAccess
# Demorou @real=6.957362000001012 segundos
Benchmark.measure do
1_000_000.times do
hash = HashWithIndifferentAccess.new(banana: 123, laranja: 321, maca: 333)
hash.merge(pera: 222)
hash.merge('uva' => 222)
end
end
# Demorou @real=3.021720999997342 segundos
Benchmark.measure do
1_000_000.times do
hash = Hash.new(banana: 123, laranja: 321, maca: 333)
hash.merge(pera: 222)
hash.merge(uva: 222)
end
end