This was the tip of the week in the Feb 25, 2021 Ruby Weekly Newsletter.

Enumerable#filter_map does exactly what its name implies: it filters on certain values and then maps over those values. Let’s look at an example of what we might have written before Ruby 2.7 introduced Enumerable#filter_map. In this example, we have an array of a few consecutive integers, and would like to calculate the squares of only the even integers:

[1,2,3,4,5,6].select { |i| i.even? }.map { |i| i ** 2 }
=> [4,16,36]

Enumerable#filter_map does both of these commands together for us! The block we need to pass to Enumerable#filter_map is a little different than the above two blocks. Enumerable#filter_map will return any non-nil results of executing a block.

It is straightforward to understand the syntax of Enumerable#filter_map if we instead think of it as doing the equivalent Enumerable#map and then Enumberable#compact operation. Let’s take a look at how we might obtain the same output as above with a map and compact:

[1,2,3,4,5,6].map { |x| x ** 2 if x.even? }.compact
=> [4,16,36]

We can use the exact same block as the map and compact with our new method, Enumberable#filter_map:

[1,2,3,4,5,6].filter_map { |x| x ** 2 if x.even? }
=> [4,16,36]

Alas, Enumerable#filter_map has turned two method calls into one! It is slick, and slightly easier than writing a select and map, or a map and compact.