Reduce method can be used to reduce a set of values to a single number / variable by performing some operation on an individual element. If unaware, you may end up using iterations such as each, map, sum to obtain the result. This tutorial illustrates how we can use reduce appropriately.
Today, I was working on an optimization work on one of the Ruby on Rails project. There was an issue with sum displayed on the consumer side.
I started debugging by finding out the controller action which returns the response that was being displayed on the UI. The value that was getting displayed on the front-end was 0. I was expecting it to be some value instead of 0.
Let’s see the example of the scenario. Let’s say, we have review score for the category of products. While debugging I came across this piece of code.
Now, the method
total_score was returning output as
Can you try and find out the reason why it could return value
by looking at the method
Incorrect usage of slice
Yes, the slice method is used incorrectly in
total_score performs following actions.
- slice key value pairs from
category_wise_review_scorehaving keys as category IDs
- Get the values from resulting hash
- Convert the invidual element into an array using map
- Sum the values from resultant array
And return the response.
I checked out git history to see why this change was done this way. I found out the older implementation as below.
Basically, it did not have
instead it has
cateogries method which returned ActiveRecord collection.
total_score method called
categories method and performed
operation which performed query like,
So, we understand from this that,
Author wanted to avoid selecting all columns from categories when querying.
just performs a query on
id column of the categories as given below.
The author was right to avoid selecting unnecessary columns
to be not used when querying
So, where was the problem?
The problem was in the usage of slice method.
slice expects comma separated values to be sliced.
Thus, array argument needs be passed as
*category_ids as given below.
This fixes the behavior and returns an expected
Can we still improve?
Yes, the way query was avoided by using Ruby methods such as,
sum was just unnecessary.
Calling all these methods introduces 4 iterations on the hash.
Thus, thing to learn from this:
Less is not always better
Don’t just go for one liners as a part of code optimization.
total_score method was changes as given below.
There is more than one way to achieve what we want in Ruby. Try and know Ruby / Rails methods and understand when they can be used appropriately to avoid such issues.
Subscribe to Ruby in Rails
Get the latest posts delivered right to your inbox