Caveat using all? and any? in Ruby17 Jun 2022
There are always several pitfalls in writing a code, regardless of its difficulty. Developers are likely to get into trouble for several hours or more. This time I will briefly describe the situation where I’ve got stuck due to a lack of recognition of the short-circuit evaluation semantics provided by all? and any? in Ruby.
What is short-circuit evaluation?
The short answer is here. It is semantic for a kind of optimization. We only evaluate the second argument of the boolean expression only if the first argument does not enough to provide the total value of the expression. For example, let’s say we have the following boolean expression.
a && b
We do not need to evaluate the variable
a' is false because we can know the overall final value is false without b`.
But what if
b have side effects, respectively? We want to make sure to execute the result of side effects. That happened when I used the
all? method in Ruby.
my_models = [...] if my_models.all?(&:valid?) puts "All okay." else puts "Someone is not okay." end
I wanted to collect all models’ errors in
my_models so that users can see all possible errors at once.
valid? allows us to accumulate validation errors in the model. But
all? stops executing
valid? if some models are already invalid. So we need to rewrite the code like this.
my_models = [...] all_validity = my_models.map(&:valid?) if all_validity.all? puts "All okay." else puts "Someone is not okay." end
This is a simple problem, and well experienced Ruby developer may not have made such a mistake. I hope this caveat may help someone who accidentally forgets the short-circuit semantics when writing the code.