This class represents a Unit. A Unit uses a given Converter with a number of registered Units in which it can be expressed. A Unit is the product of the powers of other Units. In principle, these need not be integer powers, but this may cause problems with rounding. The following code for example returns false:

  Unit.new(:m => 0.1) * Unit.new(:m => 0.2) == Unit.new(:m => 0.3)

Units can be multiplied and divided, or raised to a given power. This can only be done when both units use the same Converter. As an extra, 1 can be divided by a Unit.

Examples:

  Unit.new(:mi => 1, :s => -1) ** 2 # => mi**2/s**2
  Unit.new(:mi => 1, :s => -1) * Unit.new(:s => 1, :usd => -1) # => mi/usd
  Unit.new(:mi => 1, :s => -1, Converter.converter(:uk)) *
    Unit.new(:s => 1, :usd => -1, Converter.converter(:us)) # => TypeError
  1 / Unit.new(:mi => 1, :s => -1) # => s/mi
Methods
Attributes
[R] converter
[R] units
Public Class methods
new(units = {}, converter = Units::Converter.current)

Creates a new (composite) Unit. It is passed a hash of the form {:unit => exponent}, and the Converter to use.

Examples:

  Unit.new(:m => 1, :s => -1, Converter.converter(:uk)) # => m/s
  Unit.new(:mi => 1, :s => -2) # => mi/s**2

See also Converter, Converter.converter

# File lib/facets/more/units.rb, line 121
    def initialize(units = {}, converter = Units::Converter.current)
      @units, @converter = {}, converter
      units.each_pair { |k, v| @units[k.to_sym] = v }
      check_units
    end
Public Instance methods
*(other)

Multiplies with the given Unit.

# File lib/facets/more/units.rb, line 137
    def *(other)
      do_op(:*, :+, other)
    end
**(p)

Raises to the given power.

# File lib/facets/more/units.rb, line 128
    def **(p)
      result = {}
      @units.each_pair do |u, e|
        result[u] = e * p
      end
      Units::Unit.new(result, @converter)
    end
/(other)

Divides by the given Unit.

# File lib/facets/more/units.rb, line 142
    def /(other)
      do_op(:/, :-, other)
    end
==(other)

Returns true iff the two Units are equals, i.e., iff they have the same exponent for all units, and they both use the same Converter.

# File lib/facets/more/units.rb, line 159
    def ==(other)
      other.is_a?(Units::Unit) && other.units == units && other.converter == converter
    end
compatible_with?(other)

Returns true iff this Unit is compatible with the given Unit. This is less strict than equality because for example hours are compatible with seconds ("we can add them"), but hours are not seconds.

# File lib/facets/more/units.rb, line 166
    def compatible_with?(other)
      return false if converter != other.converter
      conv1, conv2 = converter.coerce_units(self, other)
      conv1.units == conv2.units
    end
inspect()

Alias for to_s

method_missing(m, *args, &blk)
# File lib/facets/more/units.rb, line 184
    def method_missing(m, *args, &blk)
      if converter.registered?(m)
        raise ArgumentError, "Wrong number of arguments" if args.length != 0
        return Units::Unit.new({m => 1}, converter) * self
      end
      super
    end
to_s()

Returns a human readable string representation.

This method is also aliased as inspect
# File lib/facets/more/units.rb, line 173
    def to_s
      numerator = ""
      denominator = ""
      @units.each_pair do |u, e|
        (e > 0 ? numerator : denominator) << " #{u.to_s}#{"**#{e.abs}" if e.abs != 1}"
      end
      "#{numerator.lstrip}#{"/" + denominator.lstrip if not denominator.empty?}"
    end
unitless?()

Returns true iff this Unit has all exponents equal to 0.

# File lib/facets/more/units.rb, line 147
    def unitless?
      @units.empty?
    end
Private Instance methods
check_units()
# File lib/facets/more/units.rb, line 194
    def check_units
      @units.keys.each do |unit|
        raise ArgumentError, "unit #{unit.to_s.dump} not registered" if not @converter.registered? unit
        @units.delete(unit) if @units[unit] == 0
      end
    end
do_op(op, dual_op, other)
# File lib/facets/more/units.rb, line 201
    def do_op(op, dual_op, other)
      raise TypeError, "incompatible converters for #{op}" if converter != other.converter
      result = @units.dup
      other.units.each_pair do |u, e|
        result[u] = 0 if not result[u]
        result[u] = result[u].send(dual_op, e)
      end
      Units::Unit.new(result, @converter)
    end