# What's the rules re whether a Hash can use either a Symbol or String to reference the value?

**URL:** <https://www.ruby-forum.com/t/whats-the-rules-re-whether-a-hash-can-use-either-a-symbol-or-string-to-reference-the-value/157537>\
**Category:** Ruby\
**Created:** [January 12, 2009, 9:51pm UTC](https://www.ruby-forum.com/t/whats-the-rules-re-whether-a-hash-can-use-either-a-symbol-or-string-to-reference-the-value/157537 "2009-01-12T21:51:27Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [January 12, 2009, 9:51pm UTC](https://www.ruby-forum.com/t/whats-the-rules-re-whether-a-hash-can-use-either-a-symbol-or-string-to-reference-the-value/157537/1 "2009-01-12T21:51:27Z")

</div>

Hi,  
Getting confused with Hashes a bit. It seems sometimes I can use both a  
Symbol or a String to get the value back, but other times the Symbol  
doesn’t  
work. Is there any rule re how to remember how Hash handles setting and  
getting values uses Symbol / String?

e.g. hash\_variable[:amount] versus hash\_variable[“amount”]

e.g. hash\_var = {:amount =\> 10}, versus hash\_var = {“amount” =\> 10)

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [January 12, 2009, 10:02pm UTC](https://www.ruby-forum.com/t/whats-the-rules-re-whether-a-hash-can-use-either-a-symbol-or-string-to-reference-the-value/157537/2 "2009-01-12T22:02:42Z")

</div>

On Mon, Jan 12, 2009 at 9:50 PM, Greg H.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Hi,  
> Getting confused with Hashes a bit. It seems sometimes I can use both a  
> Symbol or a String to get the value back, but other times the Symbol doesn’t  
> work. Is there any rule re how to remember how Hash handles setting and  
> getting values uses Symbol / String?
> 
> e.g. hash\_variable[:amount] versus hash\_variable[“amount”]
> 
> e.g. hash\_var = {:amount =\> 10}, versus hash\_var = {“amount” =\> 10)

In general, a hash uses eql? to know if a key matches the one you are  
asking for.  
So in general a Symbol and it’s String counterpart are not the same  
key in a hash.  
There are different implementations that allow using Strings / Symbols  
to refer to the same key.  
Search for HashWithIndifferentAccess or something like that. I think  
Rails uses something similar, IIRC.  
Maybe your confusing comes from the different behaviour when you are  
using Rails vs non-Rails?

Jesus.

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [January 12, 2009, 10:04pm UTC](https://www.ruby-forum.com/t/whats-the-rules-re-whether-a-hash-can-use-either-a-symbol-or-string-to-reference-the-value/157537/3 "2009-01-12T22:04:29Z")

</div>

Alle lunedÃ¬ 12 gennaio 2009, Greg H. ha scritto:

> Hi,  
> Getting confused with Hashes a bit. It seems sometimes I can use both a  
> Symbol or a String to get the value back, but other times the Symbol  
> doesn’t work. Is there any rule re how to remember how Hash handles  
> setting and getting values uses Symbol / String?
> 
> e.g. hash\_variable[:amount] versus hash\_variable[“amount”]
> 
> e.g. hash\_var = {:amount =\> 10}, versus hash\_var = {“amount” =\> 10)

By itself, a hash distinguish between strings and symbols, so if an  
entry is  
stored under a string key, you’ll only be able to retrieve it using a  
string  
key. If the entry has a symbol entry, then it can only be obtained using  
a  
symbol key:

h ={‘a’ =\> 1, :b =\> 2}  
puts h[‘a’] # =\> 1  
puts h[:a] # =\> nil  
puts h[:b] # =\> 2  
puts h[‘b’] # =\> nil

You can setup the hash so that it will work either with strings or  
symbols.  
For example:

hash = Hash.new do |h, k|  
if k.is\_a?(String) and h.has\_key? k.to\_sym then h[k] = h[k.to\_sym]  
elsif k.is\_a?(Symbol) and h.has\_key? k.to\_s then h[k] = h[k.to\_s]  
else nil  
end  
end

hash[‘a’] = 1  
hash[:b] = 2  
puts hash[‘a’] # =\> 1  
puts hash[:a] # =\> 1  
puts hash[:b] # =\> 2  
puts hash[‘b’] # =\> 2  
puts hash[1] # =\> nil

See the documentation for Hash.new to see how passing it a block works.

I hope this helps

Stefano

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [January 12, 2009, 10:06pm UTC](https://www.ruby-forum.com/t/whats-the-rules-re-whether-a-hash-can-use-either-a-symbol-or-string-to-reference-the-value/157537/4 "2009-01-12T22:06:50Z")

</div>

Greg H. schrieb:

> 

first:  
every time you call hash\_var[“amount”] a new string is created.  
But if you call with :amount, :amount will always be the same object.

next:  
the default Hash class does not mix String- and Symbol-Keys.  
so  
hash\_var[:amount] = 10  
hash\_var[“amount”] = 11  
hash\_var[:amount] != hash\_var[“amount”] # =\> true

but for example ActiveSupport (used in Rails) defines a class  
HashWithIndifferentAccess.  
there all Symbol-keys gets converted to a String, so that either :amount  
or “amount” point to the same entry.

So if you want to know how to handle it, ask the variable for its class  
(if someone uses monkey-patching you will lose =P)

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [January 12, 2009, 10:36pm UTC](https://www.ruby-forum.com/t/whats-the-rules-re-whether-a-hash-can-use-either-a-symbol-or-string-to-reference-the-value/157537/5 "2009-01-12T22:36:17Z")

</div>

Hi –

On Tue, 13 Jan 2009, Greg H. wrote:

> thanks guys - interesting question for the Rails guys is whether you have to  
> explicitly ask for a HashWithIndifference, i.e. just wondering whether it’s  
> possible in Rails to ask for a Hash but really get a monkey patched  
> HashWithIndiffrence back without it being obvious…

HashWithIndifferentAccess is just a subclass of Hash. I don’t think it  
can be described as monkey patched, though I’m never sure what that  
term means. Some methods return instances of it; some return instances  
of Hash.

David

–  
David A. Black / Ruby Power and Light, LLC  
Ruby/Rails consulting & training: [http://www.rubypal.com](http://www.rubypal.com)  
Coming in 2009: The Well-Grounded Rubyist ([The Well-Grounded Rubyist](http://manning.com/black2))

[http://www.wishsight.com](http://www.wishsight.com) =\> Independent, social wishlist management!

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [January 12, 2009, 10:36pm UTC](https://www.ruby-forum.com/t/whats-the-rules-re-whether-a-hash-can-use-either-a-symbol-or-string-to-reference-the-value/157537/6 "2009-01-12T22:36:31Z")

</div>

Greg H. wrote:

> thanks guys - interesting question for the Rails guys is whether you  
> have to  
> explicitly ask for a HashWithIndifference, i.e. just wondering whether  
> it’s  
> possible in Rails to ask for a Hash but really get a monkey patched  
> HashWithIndiffrence back without it being obvious…

There is no guarantees of getting any “type” back from ANY method in  
ruby… with rails, you can just convert it to an one if you aren’t  
sure…

my\_hash = HashWithIndifferentAccess.new(my\_hash)

By the way, there is no monkey patching here… HashWithIndifferentAccess  
is it’s own class. To be considered monkey patching, the Hash class  
itself would be modified to be used in an indifferent fashion…

ilan

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [January 12, 2009, 10:12pm UTC](https://www.ruby-forum.com/t/whats-the-rules-re-whether-a-hash-can-use-either-a-symbol-or-string-to-reference-the-value/157537/7 "2009-01-12T22:12:42Z")

</div>

thanks guys - interesting question for the Rails guys is whether you  
have to  
explicitly ask for a HashWithIndifference, i.e. just wondering whether  
it’s  
possible in Rails to ask for a Hash but really get a monkey patched  
HashWithIndiffrence back without it being obvious…

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [January 12, 2009, 11:31pm UTC](https://www.ruby-forum.com/t/whats-the-rules-re-whether-a-hash-can-use-either-a-symbol-or-string-to-reference-the-value/157537/8 "2009-01-12T23:31:20Z")

</div>

agreed - slip on my part to use the term - what I meant to refer to was  
“Some methods return instances of it; some return instances of Hash” -  
as  
Ilan pointed out, confirming that Rails can do this to you…

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [January 13, 2009, 8:26am UTC](https://www.ruby-forum.com/t/whats-the-rules-re-whether-a-hash-can-use-either-a-symbol-or-string-to-reference-the-value/157537/9 "2009-01-13T08:26:14Z")

</div>

On 12.01.2009 22:02, Stefano C. wrote:

> You can setup the hash so that it will work either with strings or symbols.  
> For example:
> 
> hash = Hash.new do |h, k|  
> if k.is\_a?(String) and h.has\_key? k.to\_sym then h[k] = h[k.to\_sym]  
> elsif k.is\_a?(Symbol) and h.has\_key? k.to\_s then h[k] = h[k.to\_s]  
> else nil  
> end  
> end

IMHO there is a downside to assign to the hash in the block because that  
changes the Hash. This would not work with a frozen Hash for example.

I’d probably rather adjust keys on insertion and retrieval, e.g. always  
change them to Symbols.

Kind regards

robert
