Hash Destructuring

Drew picture Drew · Mar 3, 2013 · Viewed 14.2k times · Source

You can destructure an array by using the splat operator.

def foo(arg1, arg2, arg3)
  #...Do Stuff...
end
array = ['arg2', 'arg3']
foo('arg1', *array)

But is there a way to destruct a hash for option type goodness?

def foo(arg1, opts)
  #...Do Stuff with an opts hash...
end
opts = {hash2: 'bar', hash3: 'baz'}
foo('arg1', hash1: 'foo', *opts)

If not native ruby, has Rails added something like this?

Currently I'm doing roughly this with

foo('arg1', opts.merge(hash1: 'foo'))

Answer

Andrew Marshall picture Andrew Marshall · Mar 3, 2013

Yes, there is a way to de-structure a hash:

def f *args; args; end
opts = {hash2: 'bar', hash3: 'baz'}
f *opts  #=> [[:hash2, "bar"], [:hash3, "baz"]]

The problem is that you what you want is actually not de-structuring at all. You’re trying to go from

'arg1', { hash2: 'bar', hash3: 'baz' }, { hash1: 'foo' }

(remember that 'arg1', foo: 'bar' is just shorthand for 'arg1', { foo: 'bar' }) to

'arg1', { hash1: 'foo', hash2: 'bar', hash3: 'baz' }

which is, by definition, merging (note how the surrounding structure—the hash—is still there). Whereas de-structuring goes from

'arg1', [1, 2, 3]

to

'arg1', 1, 2, 3