DEV Community

Cover image for Ruby Shortcut to Call a Method with Each Array Item as Parameter
Akshay Khot
Akshay Khot

Posted on • Originally published at akshaykhot.com

Ruby Shortcut to Call a Method with Each Array Item as Parameter

As a Ruby programmer, you probably know the &: shortcut to call a method on each item in an array. For example, this snippet will call the to_s method on :foo and :bar.

[:foo, :bar].each(&:to_s)
Enter fullscreen mode Exit fullscreen mode

The above code is similar to:

[:foo, :bar].each do |item|
  item.to_s
end
Enter fullscreen mode Exit fullscreen mode

However, instead of calling a method on the array item, you want to call a method and pass the array item to that method. Is there a one-liner for that?

[:foo, :bar].each do |item|
  puts(item)
end
Enter fullscreen mode Exit fullscreen mode

It turns out, Ruby has a corresponding &method shortcut to accomplish precisely this.

[:foo, :bar].each(&method(:puts))
Enter fullscreen mode Exit fullscreen mode

Two things are going on here.

First, the method(:puts) finds the method named puts. As per the documentation, you can access the instance variables and self method on whichever object you called method on.

method(sym) -> method

Looks up the named method as a receiver in obj, returning a Method object (or raising NameError). The Method object acts as a closure in obj's object instance, so instance variables and the value of self remain available.

Second, the Method object returned by the method method (wow, that's one too many methods) implements the to_proc method, so you can use it after &, which is to say:

If foo is an object with a to_proc method, then you can pass it to a method as &foo, which will call foo.to_proc and use that as the method's block.

&method(:puts) # is equivalent to
{ |e| puts(e) }

&:name # is equivalent to
{ |e| e.name }
Enter fullscreen mode Exit fullscreen mode

When you say &method(:puts), it finds the Method object and calls .to_proc on it.

array.each(&method(:foo))
Enter fullscreen mode Exit fullscreen mode

is equivalent to,

array.each { |e| foo(e) }
Enter fullscreen mode Exit fullscreen mode

Is It Worth It?

Now, does that mean you go ahead and replace the explicit method calls in each loops with this one-liner? Probably not.

Sometimes, that explicit method call is just what you need to keep the code readable and easier to understand. Not just for your colleagues, but for the future you. Using this one-liner adds an extra mental overhead for your brain to translate and understand what it's doing, which is not worth in many cases.

However, sometimes this shortcut is precisely what you need to express what you meant. That's why I love Ruby. The freedom to choose, do, and say whatever you want, however you want, to write software, well.

Anyway, hope that helps.

Top comments (2)

Collapse
 
w3ndo profile image
Patrick Wendo

Had no idea you could do this. Will definitely have to try it.

Collapse
 
pablomza profile image
Pablo Rodriguez

thank very much array.each(&method(:foo)) didn´t know that one