Skip to content Skip to sidebar Skip to footer

Ruby Hash Equivalent Of Javascript's Object Initializer Es6 Shorthand

In JavaScript ES6 we can create objects where variable names become keys like this: > let a = 'aaa' 'aaa' > let b = 'bbb' 'bbb' > { a, b } { a:'aaa', b:'bbb' } Does Rub

Solution 1:

Update: will be in 3.1 https://bugs.ruby-lang.org/issues/14579#note-14

No, there is no such shorthand notation.

Related proposals: #11105#13137

Rejected. I saw JavaScript new syntax, but I had no sympathy. It doesn't make anything more understandable.

Matz.

Solution 2:

Short answer no.

Longer answer

Shugo Maeda proposed a patch for this in 2015 (you can read the details about this here: https://bugs.ruby-lang.org/issues/11105).

At the time Matz wasn't into the idea, but might be willing to change his mind in the future.

In the mean time - you can make use of Shugo's patch and patch your own version of Ruby to have ES6 hash literals yourself!

To patch Ruby to add the hashes do the following:

1) Download the patch from here https://gist.github.com/thechrisoshow/1bb5708933d71e0e66a29c03cd31dcc3 (currently works with Ruby 2.5.0)

2) Use RVM to install a patched version of this Ruby. i.e.

rvm install 2.5.0 -n imphash --patch imphash.patch

Then you can use RVM to select the patched version of Ruby:

rvm use2.5.0-imphash

(Imphash is short for implicit hash)

Solution 3:

Not built in to the language. But what do you think of this?

https://gist.github.com/smtlaissezfaire/e81356c390ae7c7d38d435ead1ce58d2

defhash_shorthand(source_binding, *symbols)
  hash = {}

  symbols.each do |symbol|
    hash[symbol] = source_binding.local_variable_get(symbol)
  end

  hash
end

$ irb -r './hash_shorthand.rb'>> x = 10>> y = 20>>>> puts hash_shorthand(binding, :x, :y)
{:x=>10, :y=>20}

Only downside is that you'll need to pass the binding to get access to the local variables.

Solution 4:

Although Ruby / Rails doesn't yet support an equivalent to the ES6 shorthand syntax for hashes, there are a few handy idioms already that often come in handy.

Ruby

Consider the following method:

deftest_splat(a:, b:, c:)
  [a, b, c].inspectend

test_splat(a: 4, b: 5, c: 6) yields "[4, 5, 6]"

Although if you already have a hash such as hash = { a: 1, b: 2, c: 3 }, you can simply call it like this:

test_splat(hash) which yields "[1, 2, 3]"

Further

If you have a sub_hash, you can use it alongside other kwargs using the kwarg splat operator **. For example if you have sub_hash = { a: 1, b: 2 }, calling:

test_splat(sub_hash) yields ArgumentError: missing keyword: c

and calling:

test_splat(sub_hash, c: 3) yields ArgumentError: wrong number of arguments (given 1, expected 0)

but using the splat operator **, you can do splat the sub_hash arg:

test_splat(**sub_hash, c: 3) which yields "[1, 2, 3]"

For more reading see https://www.justinweiss.com/articles/fun-with-keyword-arguments/

Rails

The above plus a few extra methods can come in handy for Rails users, particularly in controllers when params are passed in.

Suppose you have an ActionController::Parameters object with more attributes than you need and you want a subset. E.g: { a: 1, b: 2, d: 4 }. The slice method on Hash is very handy here.

First, permit your params:

permitted_params = params.permit(:a, :b, :d).to_h.symbolize_keys.

We add .to_h.symbolize_keys because ActionController::Parameters doesn't support symbolize_keys, and kwargs require the args' keys to be symbols, not strings. So the .to_h converts it to an ActiveSupport::HashWithIndifferentAccess, and the symbolize_keys converts the hash's keys from strings to symbols.

Now, calling:

test_splat(**permitted_params, c: 3) will yield ArgumentError: unknown keyword: d as expected since d isn't a kwarg for the test_splat method. Although using slice achieves what we want here:

test_splat(**permitted_params.slice(:a, :b), c: 3) yields "[1, 2, 3]"

Solution 5:

It has been proposed in Ruby #15236 - Add support for hash shorthand and has unfortunately been rejected for the moment.

Post a Comment for "Ruby Hash Equivalent Of Javascript's Object Initializer Es6 Shorthand"