Parsing Measurements in Ruby

About two weeks ago, I released a new Ruby gem into the wild named ruby-measurement. (Unfortunately, measurement was already taken.) It serves as a means of parsing human-readable text into a quantity and unit, which can then be used for converting among units and other mathematical operations.

Let’s take a simple string like “4 1/2 dozen”. With it, we can do the following:

measurement = Measurement.parse('4 1/2 dozen')
 
puts measurement.quantity     # => 4.5
puts measurement.unit.name    # => doz
puts measurement.to_s         # => 4.5 doz

That’s pretty basic. It doesn’t appear much more useful than reading the string itself. Let’s take a more detailed example.

feet = Measurement.parse('3.25 feet')
inches = feet.convert_to(:inches)
 
puts inches.to_s              # => 39.0 in.

Okay, now this is starting to look a little more useful. But how did the convert_to call know how to convert between those units? Easy enough, unit definitions include not only the name (and aliases), but also conversion definitions for casting from one measurement to another. Here’s an example of how “feet” and “inches” are implemented (truncated for simplicity).

Measurement.define(:'ft.') do |unit|
  unit.alias :ft, :foot, :feet, :"'"
  unit.convert_to(:in) { |value| value * 12.0 }
end
 
Measurement.define(:'in.') do |unit|
  unit.alias :in, :inch, :inches, :'"'
  unit.convert_to(:ft) { |value| value / 12.0 }
end

By default, ruby-measurement ships with a variety of predefined areas, lengths, volumes, weights & capacities for both metric and U.S. customary units. With the power of the Measurement.define call, you can define any type of unit and conversion you want.

If that’s not cool enough, how about automatically casting between units when performing operations on them?

kilograms = Measurement.parse('3 1/2 kg')
grams = Measurement.parse('1275 g')
sum = kilograms + grams
 
puts kilograms.to_s           # => 3.5 kg
puts grams.to_s               # => 1275.0 g
puts sum.to_s                 # => 4.775 kg

As long as a unit define a conversion rule for casting to another unit, mathematical operation will automatically cast to the former measurement’s unit. In the above example, the kilograms object was the first measurement provided in the operation, which is why the unit chosen to perform the operation was kilograms.

To get started using this gem in your own projects, visit the ruby-measurement Github page for more details on installation and usage.

Leave a Reply

Your email address will not be published. Required fields are marked *