Ruby Cheap Tricks - Monkeypatching unit conversion

A little something I cooked up, inspired by Rails’ ActiveSupport Numeric::Bytes and friends.

  1. class Numeric
  2.  
  3.   def grams
  4.     self
  5.   end
  6.  
  7.   alias :gram :grams
  8.   alias :g    :grams
  9.  
  10.   def kilograms
  11.     self * 1000.grams
  12.   end
  13.  
  14.   alias :kilogram :kilograms
  15.   alias :kg       :kilograms
  16.  
  17.   def tonne
  18.     self * 1000.kilograms
  19.   end
  20.  
  21.   alias :tonnes :tonne
  22.  
  23.   def pounds
  24.     self * 453.59237.grams
  25.   end
  26.  
  27.   alias :pound  :pounds
  28.   alias :lb     :pounds
  29.   alias :lbs    :pounds
  30.  
  31.   def stone
  32.     self * 14.pounds
  33.   end
  34.  
  35.   def ton
  36.     self * 2240.pounds
  37.   end
  38.   alias :tons :ton
  39.  
  40.   def method_missing(method_id, *arguments)
  41.     if match = /^to_([a-zA-Z]w*)$/.match(method_id.to_s)
  42.       self / (1.0 * 1.send(match[1]))
  43.     else
  44.       super
  45.     end
  46.   end
  47. end

Being that we use the metric system in AU, I reduce all units to their respective value in grams.

  1. 10.kilograms
  2. # => 10000
  3. 1.lb
  4. # => 453.59237

And here’s the payoff: the method_missing override lets you do neat conversion tricks like:

  1. 1.kg.to_lbs
  2. # => 2.20462262184878
  3. 0.3.tonne.to_kg
  4. # => 300.0

(There is one caveat, I currently don’t check for the existence of the method given in match[1], so it’s not exactly prime time code just yet…)

Leave a Reply