57

In ruby 1.9 is there a way to define this hash with the new syntax?

irb> { a:  2 }
=> {:a=>2}

irb> { a-b:  2 }
SyntaxError: (irb):5: syntax error, unexpected tLABEL
{ a-b:  2 }
      ^

with the old one, it's working:

irb> { :"a-b" =>  2 }
=> {:"a-b"=>2}
makevoid
  • 3,276
  • 2
  • 33
  • 29

4 Answers4

64

There are some legitimate symbols that cannot be used with the new syntax. I cannot find a reference, but it appears that a symbol name matching /^[a-zA-Z_][a-zA-Z_0-9]*[!?]?$/ is allowed with the new syntax. The last character may be the special character "!" or "?".

For any symbol that does not meet these restrictions, you have to use the Ruby 1.8 syntax, :'my-symbol-name'

Wayne Conrad
  • 103,207
  • 26
  • 155
  • 191
  • 1
    Which makes sense; how is the Ruby interpreter supposed to read that, otherwise? – Trevoke Jan 25 '10 at 19:10
  • 22
    I checked in `parse.c` and it seems that with the new syntax the symbol is parsed as `tLabel` token. And matching name is more like /[a-zA-Z_][a-zA-Z0-9]/ :-) – MBO Jan 25 '10 at 19:24
  • @MBO, Extra points for going to the source. I've edited the regex in my answer. Thanks! – Wayne Conrad Jan 25 '10 at 20:11
  • 3
    @prusswan - I can't imagine a purist programming in Ruby. – Wayne Conrad Aug 21 '12 at 13:01
  • 2
    In Ruby 2.1 and Rails 4.0, passing ```data: { my_attr: 'foo' }``` to a helper method like ```button_tag``` will produce ```data-my-attr="foo"``` in the rendered HTML – Chris Beck Jan 23 '14 at 01:31
  • 1
    ? and ! are also also valid characters if they are the final characters before the colon. Similar to method names. So this is valid: `{a: 1, b?: 2, c!: 3}` – jwadsack Dec 12 '14 at 18:50
  • 1
    @ChrisBeck the same thing works with Ruby 2.0 and Rails 3.2, e.g. `data: { my_attr: 'foo' }` -> `data-my-attr="foo"`. – devius Dec 10 '15 at 15:57
24

You can combine the old and new syntax:

{a: 1, b: 2, :'c-c' => 3, d: 4}
Peter Lang
  • 54,264
  • 27
  • 148
  • 161
sl80
  • 241
  • 2
  • 2
24

To use dashes with the new syntax:

<%= link_to "Link", link_path, {data: {something: 'value1', somethingelse: 'value2'}} %>

This will generate:

<a href="/link" data-something='value1' data-somethingelse='value2'>Link</a>

This might not exactly be your particular use case, but I found this post while trying to find an answer myself so I thought I'd share my findings.

Matteo Alessani
  • 10,264
  • 4
  • 40
  • 57
Nate
  • 386
  • 3
  • 4
  • 2
    AFAIK, this is specific to the `data` attributes, if you have other attributes with dashes you have to use the old syntax. – lime Jul 18 '13 at 15:13
  • 1
    The [HAML documentation](http://haml.info/docs/yardoc/file.REFERENCE.html#html5_custom_data_attributes) mentions data attributes separately. As a bonus, you can get multiple dashes by using underscores: `data: {author_id: 123}`. Great stuff. – lime Jul 18 '13 at 15:15
11

As of Ruby 2.2, you also can use following syntax:

{a: 1, b: 2, 'c-c': 3, d: 4}
alexia
  • 14,440
  • 8
  • 42
  • 52
Stiig
  • 1,265
  • 13
  • 19