Anonymous Block Forwarding in Ruby

Anonymous Block Forwarding in Ruby

February 14, 2024

In this post, we'll take a look at the anonymous block forwarding feature added in Ruby 3.1. It lets you replace your execute(&block) calls with execute(&). Not only it saves you from coming up with a variable (most likely blk), it also looks pretty sweet. I dig it.

You probably have used (or at least heard about) the argument forwarding feature in Ruby, which was added in Ruby 2.7, that lets you forward all the arguments passed to a method, as they are, to another method, using the three dots ... syntax.

This includes all positional, named, and even block arguments.

def execute(action="", **options)
p action # get
p options # {:url=>"/test", :values=>[201, 202]}

yield "fake response"
end

def perform(...)
# execute receives all the arguments
# received by the perform function
execute(...)
end

perform action="get", url: "/test", values: [201, 202] do |result|
p result # "fake response"
end

Did you know that there's a similar shorthand to forward a block anonymously? I learned this very recently (yesterday!), and I love it.

Notice the perform method in the following example:

def execute(&blk)
yield "response 1"
blk.call "response 2"
end

def perform(&)
# execute receives the same block
# received by the perform function
execute(&)
end

perform do |result|
p result
end

# Output:
# "response 1"
# "response 2"

Earlier, you'd have done something like:

def perform(&blk)
execute(&blk)
end

But starting in Ruby 3.1, you can do this:

def perform(&)
execute(&)
end

Pretty cool, right? Also looks pretty nice, in my opinion. What do you think?

If you like this syntax, and would like to enforce it via Rubocop (Rails 8 ships with a default Rubocop linter out of box), you can use the following Rule:

Naming/BlockForwarding:
EnforcedStyle: anonymous

On the other hand, if you prefer the older explicit version, enforce it with this rule:

Naming/BlockForwarding:
EnforcedStyle: explicit

P.S. For an in-depth explanation, I suggest reading this post from zverok. It goes into much more depth.

Sign up for my newsletter

Let's learn to become better developers.

Comments (2)

M
Mathieu Eustachy

Pretty nice! Thanks for the article (again)

R
Rob Hill

Very cool.

Sign in to leave a comment.