Guarding with arrays

guard
Brian Cardarella

CEO & Founder

Brian Cardarella

This week I applied a pattern I’ve been using for years to two separate pull requests from our devs. (I like to review almost all of the code that DockYard devs write)

In both cases I was able to help them refactor their code to use an enumerator as code guards instead of conditional statements. Let’s take a look at each example:

users = User.where(type: 'employee')

if users.any?
  users.each do |user|
    # ...
  end
end

In this first example the each is avoided if the users collection is empty. However, with arrays the enumerator only acts on each member of the collection so we don’t need to avoid if the collection is empty. We can refactor the above code into something like this:

User.where(type: 'employee').each do |user|
   # ...
end

Much cleaner!

The next example may not be as straight forward but as we’ll see with Ruby we can clean this up nicely.

if params[:ids]
  params[:ids].each do |id|
    # ...
  end
end

Here we have a situation where params[:ids] could contain a collection of data. Or it could be nil. Because of this we cannot just assume we can always iterate over that value. In Ruby we can create a new Array:

Array([1,2,3])
# => [1,2,3]

Array(nil)
# => []

Notice in the second example that when we pass nil it creates an empty array. Knowing this we can refactor our code:

Array(params[:ids]).each do |id|
  # ...
end

If you find yourself putting guards around enumerators odds are you can refactor in a similar manner as I’ve shown above.

BTW, I’ve been using this pattern for years but I don’t know if there is an actual name for this. If you do please share!

Newsletter

Stay in the Know

Get the latest news and insights on Elixir, Phoenix, machine learning, product strategy, and more—delivered straight to your inbox.

Narwin holding a press release sheet while opening the DockYard brand kit box