Aug 22

Turn a decision into a method

dastels @ 3:19 am

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.



Steve Jobs Memorial

Stay Hungry, Stay Foolish!
Steve Jobs

In memory of Steve Jobs