The Arguments Forwarding shorthand in Ruby 2.7
How to 3-dots operator can be used to automatically forward arguments to another method call
In Ruby, it occurs that a method directly forwards arguments to another one
Here, forwarding *args, **kwargs, &blk
is redundant and it impacts the readability of the code. To overcome this problem, Ruby 2.7 introduced the arguments forwarding shorthand
In the above example, everything passed to Exporter.run
is forwarded to new
. As new
calls initialize
then Exporter#initialize
receives all the arguments passed to the call of Exporter.run
.
Neat!
Now, what happens if Exporter.run
needs to manipulate arguments to instantiate the right exporter, for example?
produces
syntax error, unexpected def self.run(type, ...)
^^^
Indeed, the arguments forwarding shorthand can’t be mixed with other arguments and it also can’t be destructured.
The above feature enhancement is in discussion since December 2019. So what if you still want to manipulate arguments before forwarding them to another method call?
Feel free to have a look at the module_function vs extend self article if you’re not familiar with the module_function method.
In Exporter.run
method, we declare a proc
that takes 2 arguments:
*_
: regular arguments (unused in the block)**kwarg
: keywords arguments
In this block, we check if type
passed as a keyword argument is whitelisted by Exporter
. If so, we instantiate the right exporter by forwarding all the arguments using the Argument Forwarding shorthand—we instantiate Exporter::CSVExporter
in this case.
Finally, we call the generate_export
method on our freshly instantiated exporter.
The block passed to our proc
can manipulate the arguments because the Argument Forwarding shorthand is passed to call
. So the arguments passed to call
are directly passed as arguments of the block.
UPDATE: Ruby 3
Arguments forwarding now supports leading arguments:
def method_missing(meth, ...)
send(:"do_#{ meth }", ...)
end
RubyCademy’s Newsletter
In the RubyCademy newsletter, I share what I’m learning about Ruby & Rails, including helpful tips, code insights, and exclusive Ruby Cards with detailed explanations.
If it sounds helpful, feel free to subscribe for free:
Thank you for taking the time to read this message!