Aug 22 2006
Turn a decision into a method
I was just working on some code that needed to extract some optional data from a hash, using it to set an attribute on a Model object. If it wasn’t present in the hash, a default should be used.
I started with something like:
if hash.has_key?("Genre")
genre_name = hash["Genre"]
else
genre_name = "Undefined"
end
Maybe that could be simplified some:
genre_name = hash.has_key?("Genre") ? hash["Genre"] : "Undefined"
Better.. but it still obscures what the intent of this method is.
I ended up extracting the code out into a separate method, and used a guard clause to make the decision:
genre_name = genre_name_or_default(hash)
...
def genre_name_or_default(hash)
return hash["Genre"] if hash.has_key("Genre")
"Undefined"
end
Clean, very clear.
I might want to use a default for the hash, but for now that’s YAGNI, and this works nicely for my purposes.
Addendum
As Jens points out in his comment, I can use hash.fetch(key, default) for this. In fact that’s what I’ve ended up doing in tis case. However, it is a generally useful approach to extract troublesome or ugly logic into a method of it’s own. Quite often being in a method (and not being afraid to have multiple return points) can drastically simplify and/or clarify logic.
Addendum 2
Simon points out that the default behaviour that the default behaviour of Hash.[] is to return nil. Which in this case will, indeed, mean that the key wasn’t present. So
hash["Genre"] or "Undefined"
works great.
