In some part of my code I ended writing the following:
self.count_processed ||= 0
self.count_processed += 1
where self
is some ActiveRecord model, and count_processed
is an attribute of that model (and stored in the database). What am i trying to achieve (if it is not blatantly obvious):
- if
count_processed
is not initialised, make it zero - increment
count_processed
Imho this code is clear and readable, but I had the feeling it could be more concise/prettier. So I asked that question on our campfire, to see if we could come up with something shorter. Very nice to be working in a team where you can just throw up questions like these and a very useful, educational discussion unfolds. In short we came up with the following solutions.
Solution 1: to_i
self.count_processed = self.count_processed.to_i + 1
Nifty! Isn't it? Use to_i
because it will handle the nil
correctly. But for me this looked wrong. If I would return to this code after a few weeks, months, I would wonder why I did this way, and not just wrote self.count_processed += 1
. So while the code is correct, the intent of the code is not clear.
Solution 2: concise!
self.count_processed = (self.count_processed || 0) + 1
This is very beautiful, and the intent is also very clear. If it is not initialised, use the zero, else just use the value and add 1. Awesome.
Solution 3: change the getter
An alternative solution would be to overwrite the getter, like this
def count_processed
self[:count_processed] ||= 0
end
Note the notation we used: we use self[:count_processed]
because this will fetch the value from the database column. If this was a normal getter, we would write @count_processed
(but that does not work for an ActiveRecord model). After redefining the getter, we can just write: self.count_processed += 1
While this will work always, does it express its intent more clearly or not? Actually you no longer have to worry about the initialisation, because it is handled, and we can focus on what we really want: increment the counter. I opted for this solution.
What about you?
Which version do you prefer? Do you have any alternative suggestions?