Reputation: 2525
I am trying to deal with inconsistent keys (Strings/Symbols) in hashes. I thought that HashWithIndifferentAccess would be the answer but I am getting some slightly confusing results when trying to do some basic operations on these hashes
For example I have the following HashWithIndifferentAccess
(rdb:1) metadata
{"indexes"=>["respondent", "brand"], "columns"=>["rating"],
"value_labels"=>{}, "column_labels"=>{}}
(rdb:1) metadata.class
ActiveSupport::HashWithIndifferentAccess
when I try the following select I get an empty hash
(rdb:1) metadata.select{ |k, v| [:indexes, :columns, :value_labels, :column_labels]
.include? k }
{}
Are all common hash operations available with HashWithIndifferentAccess ? Why is this operation returning an empty hash
Upvotes: 1
Views: 2678
Reputation: 34774
All you really get with HashWithIndifferentAccess
is the ability to set and get values using either a string or a key. Once you start using other reading methods on the hash you move to objects that are not indifferent to strings or symbols.
However, HashWithIndifferentAccess
does help you because:
Internally symbols are mapped to strings when used as keys in the entire writing interface (calling []=, merge, etc)
....
You are guaranteed that the key is returned as a string
This means that you're always going to get a string for keys with methods like select
:
> h = { sym_key: 'sym_value', 'string_key' => 'string_value' }.with_indifferent_access
> h.keys
=> ["sym_key", "string_key"]
Upvotes: 6
Reputation: 198438
Indifferent access means HashWithIndifferentAccess#[]
will check both strings and keys. However, there is no such patch done on Array#include?
, which you are using to filter your data. Easy fix:
[:indexes, :columns, :value_labels, :column_labels].include? k.to_sym
Upvotes: 3