Ruby guard clauses: How you can refactor nested ifs and other conditional logic

Original image source: inspiremusic.com/en-garde

This short refactoring tutorial will explain how you can write guard clauses for your if statements, rather than using nested if .. else conditional logic. This can help you to create clean and easy to read code.

It will give examples using Ruby, but the same programming style can apply to other languages. If you are coding in JavaScript then checkout this tutorial with examples using JavaScript.

Avoid nested if .. else logic

What may start off as one set of conditions managed by an if .. else block can easily become difficult to understand when more and more if .. else logic is added to manage various conditions.

def admin?(user)
if (user.role == 'admin')
if (user.manager == true)
return true;
else
return false;
end
else
return false;
end
end

This can result in code where it is challenging for developers to follow the flow of logic, as well as be time consuming to maintain or amend code later on. An alternative programming style is to use guard clauses, which achieve the same outcomes but can be easier to read.

The guard clause

This structure guards the flow of logic from continuing if certain conditions are met, or not met.

return ACTION if CONDITION

Guard clauses can reduce the number of lines in your methods, classes, etc. A result of using multiple guard clauses is that you can see what conditions trigger certain code to be executed.

return false if (user.role != 'admin')

Here is the original method’s code refactored using guard clauses.

def admin?(user)
return false if (user.role != 'admin')
return false if (user.manager != true)
true
end

Note how the number of lines of code has reduced from 13 to 5!

Image source: theattic.london/2015/07/05/en-garde-an-unexpected-lesson

Further refactoring using code extractions

A further way to develop this refactoring strategy is to extract code to other methods, classes or modules, which are then called within guard clauses. It means you can use more complex conditional logic for an if statement within a guard clause. Here is a simple example of code extracted to separate methods.

def has_admin_role?(user)
user.role == 'admin'
end
def is_senior_manager?(user)
user.manager == 'senior'
end

Now you have extracted key logic, you can unit test these independently from the original code. This can help you to identify, isolate and iron out bugs within a large code base.

Here are the extracted methods applied to the original example.

def admin?(user)
return true if (has_admin_role?(user) && is_senior_manager?(user))
false
end

It can even be refactored down to 3 lines for the original method.

def admin?(user)
has_admin_role?(user) && is_senior_manager?(user)
end

En conclusion!

Applying this strategy to a complex code block can help you gain control of your code logic in way that makes code maintainable and scalable. Refactoring is an art form and there are always ways to keep refining this skill as a developer.

Recommended books on Ruby programming

I have found these books helpful when learning to program Ruby and develop applications. These contain Amazon affiliate links. If you click through & make a purchase, I will earn a commission at no additional cost to you.

Read more from ryanwhocodes