Hash has_key? syntax

11,185

Solution 1

There are strings and there are symbols. A string is not a symbol.

These hashes contain a symbol as a key:

{key: "value"}
{:key => "value"}

This hash contains a string as a key:

{"key"=>"value"}

That's why your tests behave like they do.

Rails has a wrapper for Hash, called HashWithIndifferentAccess. If you have one of those, you can access values by either strings or symbols. But for regular hashes, there's distinction.

require "active_support/core_ext"

h = {key: "value"}.with_indifferent_access

h.has_key?(:key) # => true
h.has_key?("key") # => true

Solution 2

If you observe while you assign the hashes, in IRB they're like this:

2.0.0p247 :014 > a = {key:"values"}
 => {:key=>"values"} 
2.0.0p247 :015 > b = {"key" => "values"}
 => {"key"=>"values"} 
2.0.0p247 :016 > c = {:key => "value"}
 => {:key=>"value"} 

We can see that a and c are the same, other than the syntax used for assigning. The syntax used for c is I guess the old syntax.

a = {key:"values"} 

is the syntax introduced in the latest Ruby version. In both hash a and c, the key is a symbol.

"The Difference Between Ruby Symbols and Strings" explains the difference between string and symbol, whereas in hash b the key value is a string. Apparently its value is "key". The major difference is the value of key for hash b is mutable while it's not true in case of hash a.

Share:
11,185
Micka
Author by

Micka

Updated on June 04, 2022

Comments

  • Micka
    Micka almost 2 years

    I have three Hashes:

    a = {key:"value"}
    b = {"key"=>"value"}
    c = {:key=>"value"}
    

    And these results:

    a.has_key?("key") # => false
    b.has_key?("key") # => true
    c.has_key?("key") # => false
    

    My questions are:

    • Why? What is this behavior?
    • How can I get a, b and c to return true using the same syntax for all of them?