Newish Cool Ruby methods

By AKM
February 10, 2025
Here are 5 Ruby methods that are very helpful but may be not very widely known yet
tap

tap method takes a block, yields the object to that block and finally returns the original object from that block. Let's look at an example. Let us say you have an list. You call a long chain of methods on that list.

> mylist = [45, 3, 23, 78, 432, -91, 45]
=> [45, 3, 23, 78, 432, -91, 45]
> mylist.select { |n| n > 0 }.map { |n| n*n }.sort.first(5)
=> [9, 529, 2025, 2025, 6084]

Here, the list is being transformed successively in each of the method call in the chain - select, map, sort and first. Let's say, the final result looks incorrect to you and you would like to examine the intermediate value of the list in the chain. This is how it can be done:

> arr.select { |n| n > 0 }.tap { |n| puts "Step 2: #{n}" }.map { |n| n*n }.sort.first(5)
Step 2: [45, 3, 23, 78, 432, 45]
=> [9, 529, 2025, 2025, 6084]

Note that the final result didn't change at all. You just got a peek at the intermediate state of the list. Sometimes, this kind of ability to look at the intermediate values in a method chain is useful for debugging. Another use case is that you can operate on an intermediate values e.g. store them in a DB table, without effecting the chain of method calls.

tap mimics the tee shell command. It has been available since Ruby 1.8.7

then

Like the tap method described above, then also takes a block, yields the object to the block and finally returns the result of the code within the block. Note that the return value is different from what tap does. Let us see its usefulness through an example. Say, you have defined a little utility method

# shorten a name to just 3 characters
def shorten_name(s)
  s.size > 3 ? s.first(3) : s
end

# call it like this    
> shorten_name("mumbai") # "mum"
=> "mum"
> short_name("goa") # "goa"
=> "goa"

However, you need to transform a name string using a chain of methods

# Capitalise the first letter, shorten it and finally put spaces between letters
> name = "Indore"
> short_name(name.upcase_first).split(//).join(" ")
=> "I n d"

However, the method calls now no longer reads like a chain. It would have looked much better if we could write instead:

> name.upcase_first.short_name.split(//).join(" ") # does not work

Turns out we can make it pretty close using then method:

> name.upcase_first.then { |n| short_name(n) }.split(//).join(" ") # this works!
=> "I n d"

Note that, yield_self is an alias for then method. It has been available Since Ruby 2.6.3

.()

This is also referred to as call shorthand operator. Calling .() on any object is same as invoking the call method on that object. Since lambdas have a call method defined on them, it can be used to execute lambdas. Here is an example:

# define a lambda
> sqr = lambda { |n| n*n }
> sqr.call(3)
=> 9
> sqr.(3) # just a shorthand for sqr.call(3)
=> 9

.() can be invoked on any Object and not just Procs and Lambdas. As long as that object has a call method defined, it will work. This has been available since Ruby Since 2.7

As an aside, note that sqr[3] and sqr::(3) are also valid ways of calling a lambda but are not related to call shorthand operator.

.&

This is also called safe navigation operator. It can be used just like the dot operator to call any method on an object. The only difference is that it will not raise an exception if the object is nil. Hence it is "safer" than the dot operator. Here is an example:

> name = "delhi"
> name.upcase
=> "DELHI"
> name = nil
> name.upcase # this will throw a nil exception since name is nil

> name.&upcase # No exception, upcase will only be called if name is non-nil. Otherwise nil is returned
=> nil

Using the .& to call methods make it safe to chain method calls.
> name&.upcase&.first(3) # works even when name is nil
    
Note that this method is inspired from Rails' try method.
> name.try(:upcase) # same as name.&upcase

This has been available since Ruby 2.3

curry

Currying is a functional programming technique where a function taking multiple arguments is transformed into another function taking lesser number of arguments. In Ruby, you can call curry method on a proc. It returns a curried proc. You can then call that curried proc just like a regular proc and pass some arguments. If you pass all the arguments, it call the the original proc and returns the result. Otherwise, it returns another curried proc, which will now take fewer arguments.

Here is an example:

# Define a method to calculate x2 + y3+ z4
> series_sum = lambda { |x, y, z| x**2 + y**3 + z**4 }
> series_sum.(2,3,4)
=> 287

Let us say we want to fix the value of x to a known value and want a simpler function which takes only two arguments now. We can do it like this:
> f2 = series_sum.curry[2]

This returns a new lambda f2 which is same as the original lambda except that the first argument x is now fixed to 2. We can now call this new lambda
> f2.(3, 4)
=> 287 
> f2.(0, 0)
=> 4

If we call f2 with just one argument, we get another lambda now with both first and second arguments fixed
> f3 = f2.(3)
> f3.(4)
=> 287

Once all the arguments are supplied, then the original lambda is executed and the result returned.
/ / / /