Ruby hash equivalent of JavaScript's object initializer ES6 shorthand
Asked Answered
M

6

21

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 Ruby have something equivalent for hashes?

Clarification: Obviously this question regards the shorthand notation. I'm looking for {a,b} not {a:a,b:b}.

Mozellamozelle answered 21/5, 2016 at 16:22 Comment(0)
A
23

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.

Aiello answered 21/5, 2016 at 16:28 Comment(2)
I wish there was, though... :)Revolutionary
Well, there's not much to understand: if you see an object without the regular key: value syntaxt, then it's the shorthand - it's an useful feature, it tries to make you use consistent names when moving data.Knickknack
G
6

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 use 2.5.0-imphash

(Imphash is short for implicit hash)

Gooden answered 21/2, 2018 at 11:15 Comment(0)
A
2

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

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

def hash_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.

Angleworm answered 15/7, 2020 at 3:44 Comment(0)
G
2

Starting from ruby 3.1, it can be done like this:

x = 1
y = 2

{x:, y:}
# => {:x=>1, :y=>2}

Values can be omitted for functions too:

def x
  1
end

def y
  2
end

{x:, y:}
# => {:x=>1, :y=>2}

Playground

Glaciate answered 13/2, 2023 at 5:51 Comment(0)
S
1

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:

def test_splat(a:, b:, c:)
  [a, b, c].inspect
end

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]"

Shipp answered 20/9, 2018 at 16:16 Comment(0)
H
1

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

Highstepper answered 12/2, 2020 at 1:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.