How to create symbol (hash key) from association,

2019-01-20 05:54发布

Sorry, I'm not even sure how to ask this question.. so if you could suggest around that as well, it would be appreciated.

# A. WORKS, but "stockroom" is hardcoded
render partial: association.to_s.singularize + '',
  locals: {stockroom: new_object}

# B. WORKS, but uses old syntax
render partial: association.to_s.singularize + '',
  locals: {association.to_s.singularize.to_sym => new_object}

# C. does NOT work
render partial: association.to_s.singularize + '',
  locals: {association.to_s.singularize.to_sym: new_object}

# D. does NOT work
ass = association.to_s.singularize.to_sym
logger.debug "--- ass: #{ass.inspect} (#{ass.class})"
  # => --- ass: :stockroom (Symbol)
render partial: association.to_s.singularize + '', locals: {ass: new_object}

Not that the old syntax is a bad thing, I'm just wondering if there's a way to do this using the new syntax (even via an intermediary (i.e. ass)).

标签: ruby hash symbol
1条回答
霸刀☆藐视天下
2楼-- · 2019-01-20 06:51

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.

查看更多
登录 后发表回答