Ruby guard clauses: How you can refactor nested ifs and other conditional logic
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!
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.
- The Well Grounded Rubyist by David A. Black — This explains the fundamentals of Ruby programming in a clear, comprehensive way.
- Practical Object Oriented Design in Ruby by Sandi Metz — Covers how to design classes and other Ruby objects using OOP design.
- Effective Testing With RSpec 3 by Myron Marston and Ian Dees — Teaches the syntax and best practices for Ruby’s RSpec testing library.