Search code examples
rubysyntaxhashruby-1.9hashrocket

Is there any difference between the `:key => "value"` and `key: "value"` hash notations?


Is there any difference between :key => "value" (hashrocket) and key: "value" (Ruby 1.9) notations?

If not, then I would like to use key: "value" notation. Is there a gem that helps me to convert from :x => to x: notations?


Solution

  • Yes, there is a difference. These are legal:

    h = { :$in => array }
    h = { :'a.b' => 'c' }
    h[:s] = 42
    

    but these are not:

    h = { $in: array }
    h = { 'a.b': 'c' } # but this is okay in Ruby2.2+
    h[s:] = 42
    

    You can also use anything as a key with => so you can do this:

    h = { C.new => 11 }
    h = { 23 => 'pancakes house?' }
    

    but you can't do this:

    h = { C.new: 11 }
    h = { 23: 'pancakes house?' }
    

    The JavaScript style (key: value) is only useful if all of your Hash keys are "simple" symbols (more or less something that matches /\A[a-z_]\w*\z/i, AFAIK the parser uses its label pattern for these keys).

    The :$in style symbols show up a fair bit when using MongoDB so you'll end up mixing Hash styles if you use MongoDB. And, if you ever work with specific keys of Hashes (h[:k]) rather than just whole hashes (h = { ... }), you'll still have to use the colon-first style for symbols; you'll also have to use the leading-colon style for symbols that you use outside of Hashes. I prefer to be consistent so I don't bother with the JavaScript style at all.

    Some of the problems with the JavaScript-style have been fixed in Ruby 2.2. You can now use quotes if you have symbols that aren't valid labels, for example:

    h = { 'where is': 'pancakes house?', '$set': { a: 11 } }
    

    But you still need the hashrocket if your keys are not symbols.