Reputation: 15863
How I can pass the keyword arguments to a call to another method in my code without specifying each of them.
Consider the following method with the new first-class support for kwargs:
def foo(obj, bar: 'a', baz: 'b')
another_method(bar, baz)
end
Consider the old Ruby options hash syntax:
def foo(obj, options = {})
another_method(options)
end
I want to pass the keyword arguments without specifying each of them explicitly as with the case of the old options hash syntax. Is that even possible?
Upvotes: 3
Views: 1216
Reputation: 2253
Keyword arguments work similarly to your "old Ruby options hash syntax". A hash's keys will substitute as keywords and their values as arguments. This should work fine:
def foo(obj, bar: 'a', baz: 'b')
another_method(bar, baz)
end
arg_hash = { bar: 'alt bar', baz: 'alt baz' }
foo(Object.new, arg_hash)
If your hash keys are strings, such as { 'bar' => 'alt bar', 'baz' => 'alt baz' }
, this won't work. You'll get an ArgumentError: wrong number of arguments (2 for 1)
error. This is easy enough to fix in Rails by calling .symbolize_keys
on the hash. If you're not in Rails, you'll have to convert the keys manually or reimplement that method.
Also, in Rails, a HashWithIndifferentAccess (such as the params
hash in a controller), although it has both strings and symbols for keys, can't be used in this way. If you pass params
, it will look at the string keys instead and you'll get the same error as above. I'm not sure why this is the case, but my guess it's because the params hash starts with strings and adds symbols so the symbols are secondary and not the default. Total guess on that though.
Upvotes: 0
Reputation: 15703
You can use the double-splat operator:
def a(q: '1', w: '2')
p q
p w
end
def b(**options)
a(options)
end
b
# => 1
# => 2
b(q: '3', w: '4')
# => 3
# => 4
Upvotes: 3