How to Create Symbol (Hash Key) from Association, Using New Ruby (1.9) Hash Syntax

How to create symbol (hash key) from association, using new ruby (1.9) hash syntax?

The JavaScript style syntax is not really the new syntax, it is just an alternate syntax in 1.9 that can be used for some symbol literals within a Hash literal.

You can't use the trailing-colon style with all symbols, try these and you'll see:

{ :$set => 11 }                       # Valid
{ $set: 11 } # Invalid
{ :'where.is.pancakes.house?' => 23 } # Valid
{ 'where.is.pancakes.house?': 23 } # Invalid

Similarly, if you have a symbol that isn't a symbol literal:

s = o.to_sym; { s => 42 }
{ o.to_sym => 42 }

then you have to use the fat arrow syntax in your Hashes. The same applies if you have a key that isn't a symbol:

a = %w{where is pancakes house?}
h = { a => 11 }
g = { a: 11 } # Also works but produces a completely different result!

In summary, the trailing-colon converts some literal values (I think anything that matches /\A[a-z_]\w*\z/i but I'm not certain) that precede it to symbols when used inside a Hash literal. Basically, the JavaScript style is useless in all but the most trivial cases; but the trivial cases do happen to be the most common.

The only way I can think of to use the JavaScript style with a non-literal symbol would be an abomination like this:

ass = association.to_s.singularize.to_sym
h = eval "{ #{ass}: 'pancakes' }"

and if you ever put something like that in real code then may the gods have mercy on your soul.

Also, keep in mind that you have to use the leading-colon form of the symbol when you want to access your hash:

h[:pancakes] # Valid
h[pancakes:] # Invalid

so the JavaScript style is of limited utility.

Using symbols as hash keys

That's correct. A symbol is always defined with the colon before the name

:foo

The original notation for the Hash with symbol keys was

{ :foo => "bar" }

However, since Ruby 1.9, there is an alternative notation that was designed to be more compact.

{ foo: "bar" }

The two notations are equivalent. However, this is a specific Hash exception. The following is not a valid symbol declaration on its on

foo:

Is Hash Rocket deprecated?

The author of that blog post is being overly dramatic and foolish, the => is still quite necessary. In particular:

  1. You must use the rocket for symbols that are not valid labels: :$set => x is valid but $set: x is not. In Ruby 2.2+ you can get around this problem with quotes: '$set': x will do The Right Thing.

  2. You must use the rocket if you use keys in your Hashes that aren't symbols, such as strings, integers or constants. For example, 's' => x is valid but 's': x is something completely different.

You can kludge around the above in the obvious manner of course:

h = { }
h[:'where.is'] = 'pancakes house?'
# etc.

but that's just ugly and unnecessary.

The rocket isn't going anywhere without crippling Ruby's Hashes.

Ruby on Rails: how we should write symbol - symbol: vs :symbol =


To help you decide which hash literal syntax to use, check out:

  • Why using the hash rocket syntax is still sometimes necessary.

  • Ruby Style Guide which the Rails Style Guide adheres to.

Snippet from the Ruby Style Guide on Collections:

Preferably use symbols instead of strings as hash keys.

# bad
hash = { 'one' => 1, 'two' => 2, 'three' => 3 }

# good
hash = { one: 1, two: 2, three: 3 }

Use the Ruby 1.9 hash syntax when your hash keys are symbols.

# bad
hash = { :one => 1, :two => 2, :three => 3 }

# good
hash = { one: 1, two: 2, three: 3 }

Don't mix the Ruby 1.9 hash syntax with hash rockets in the same hash literal.

When you've got keys that are not symbols stick to the hash rockets syntax.

# bad
{ a: 1, 'b' => 2 }

# good
{ :a => 1, 'b' => 2 }

Ruby: colon before vs after

You are welcome for both, while creating Hash :

{:name => "foo"}
#or
{name: 'foo'} # This is allowed since Ruby 1.9

But basically :name is a Symbol object in Ruby.

From docs

Hashes allow an alternate syntax form when your keys are always symbols. Instead of

options = { :font_size => 10, :font_family => "Arial" }

You could write it as:

options = { font_size: 10, font_family: "Arial" }

Best way to convert strings to symbols in hash

In Ruby >= 2.5 (docs) you can use:

my_hash.transform_keys(&:to_sym)

Using older Ruby version? Here is a one-liner that will copy the hash into a new one with the keys symbolized:

my_hash = my_hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}

With Rails you can use:

my_hash.symbolize_keys
my_hash.deep_symbolize_keys

How to correct syntax highlighting for setting Rails link or form field class in Sublime/Textmate 2

I think it's to do with the precedence in terms of syntax highlighting. Because the keywords for ruby matches "class" it is trying to highlight it as though you had class MyClass. Whereas the old format of hashes had the preceding : to stop it from being picked up as a keyword.

Disclaimer: I'm no expert on this stuff was just tinkering and the following worked for me.

If you edit your Ruby.tmLanguage file (in Packages/Ruby) you can move the section that defines keywords below the section that defines the new ruby 1.9 hash syntax. That way it should prioritize the new hash syntax.

Look for a <dict> entry that contains:

<dict>
....
<key>name</key>
<string>keyword.control.ruby</string>
</dict>

and put it below the entry like:

<dict>
....
<key>name</key>
<string>constant.other.symbol.ruby.19syntax</string>
</dict>

In Ruby what is the meaning of colon after identifier in a Hash?

The colon in this context denotes a literal Hash.

factory is the Hash key, :user is the value.

The alternative syntax is :factory => :user. They mean the same thing.

Why are hyphens invalid in JS-like syntax for hashes in Ruby

Colon hash syntax does not support all symbols. Sometimes you must use hashrockets. Have a look here.

foo: true boils down to :foo => true. In symbols, dashes must be escaped like that: :'foo-bar'. foo-bar: true is not valid because :foo-bar => true is not, too.



Related Topics



Leave a reply



Submit