Ruby Hash Syntax: Hashrocket vs JSON-Style

At a first glance the 1.9 ruby hash syntax looks like a simple change. No longer using the infamous “Hashrocket” and moving to a familiar JavaScript Object Notation.

{:cat => 'meow'} # 1.8
{cat: 'meow'} # 1.9

On an average day I write equally as much JavaScript as I do Ruby so the new 1.9 syntax is an easy swtich for me.

Do these updates to the syntax mean that we’ll be seeing the demise of the 1.8 syntax anytime soon? Definitely not.

The syntax change isn’t that simple. There are certain things you simply can not do with the new 1.9 syntax.

Keys do not have to be symbols or strings

You can actually use any object in the language as a key in a hash. The most common are Symbols and Strings. Less used are Classes, Objects, Floats or pretty much anything that is an object in Ruby. Which is pretty much everything.

The catch here is the 1.9 syntax only supports symbols as keys. So if you need to use any kind of hyphanated string or special object as a key you will need to use the hashrocket syntax. Some examples:

{'cats-meow': 'meow'}
=> syntax error, unexpected '}', expecting $end
{:'cats-meow' => 'meow'}
=> {:'cats-meow' => 'meow'}

{1.2 => 'meow'}
=> {1.2=>"meow"}

class Cat; end
c = Cat.new
{c => 'meow'}
=> {#<Cat:0x007fd5512f41c0>=>"meow"}

{String => 'a string'}
=> {String=>"a string"}

Two different Symbols

Another catch is that the 1.9 syntax is the only place in ruby where a symbol is represented differently. A symbol is normally preppended with a colon. ex. :mysymbol. Only in the 1.9 hash syntax is the symbol represented without the preppended colon and then following the JSObject Notation has a colon at the end of the symbol defining the key value relationship. The inconsistent use of Symbols like this could lead to confusion for people new to the language.

Mixing the syntax

You can also mix the JSON and Hashrocket syntax. Although for the sanity if your fellow developers please do not.

{cat: 'meow', :dog => 'bark'}
=> {:cat=>"meow", :dog=>"bark"}

The 1.9 syntax can also look extremely weird when passing Symbols as values:

{cat: :meow, dog: :bark, owl: :hoot}
=> {:cat=>:meow, :dog=>:bark, :owl=>:hoot}

Keys are now unordered

Aside from the syntax change; ruby 1.9 also treats the ordering of the key/values differently. In ruby 1.9 the keys are no longer ordered. Although after some playing around I found my 1.8.7 REE install was not exactly ordering the hash as I was expecting.

{:dog => 'bark', :owl => 'hoot', :cat => 'meow'} # 1.9
=> {:dog=>"bark", :owl=>"hoot", :cat=>"meow"}

{:dog => 'bark', :owl => 'hoot', :cat => 'meow'} # 1.8.7
=> {:owl=>"hoot", :cat=>"meow", :dog=>"bark"}

Which one should I use?

The Github Ruby Styleguide suggests just to use the hashrocket syntax 100% of the time.

It really is a personal/team preference on the syntax choice. I think consistency is the most important thing. As long as you are doing it the same throughout your code.