Yesterday, I introduced a bug into our codebase by calling
#titleize on a string that could possibly come in as
def route medication.route_name.titleize end
This threw an error on production and a coworker fixed this by adding
def route medication.route_name.try(:titleize) end
I'm not totally happy with this solution, after being really influenced by Avdi's article on
#try, and I've been trying to come up with something I like better. Here are two possibilities.
Firstly, in Avdi's talk "Confident Code", he talks about asking for the data type you need: if you need a string, ask for a string. So I thought about this:
def route medication.route_name.to_s.titleize end
nil will be converted to empty string, and
#titleize will be called, which will not error. The obvious issue with this is that you're calling
#to_s on something which is only ever an instance of
The only other approach I could think of was this:
def route medication.route_name.present? medication.route_name.titleize : '' end
The issue here is the
if/else parading around as prettier code through the use of a ternary operator, and the repetition of
medication.route_name. This could be minified by delegating
medication, or some other work around. But there's still the
if/else conditional. And that's more code.
The bigger question here is how to handle
nil values. This method is a pretty typical example of how this comes up. How would you handle it?