class Unitwise::Measurement

A Measurement is a combination of a numeric value and a unit. You can think of this as a type of vector where the direction is the unit designation and the value is the magnitude. This is the primary class that outside code will interact with. Comes with conversion, comparison, and math methods.

Public Class Methods

new(*args) click to toggle source

Create a new Measurement @param value [Numeric] The scalar value for the measurement @param unit [String, Measurement::Unit] Either a string expression, or a Measurement::Unit @example

Unitwise::Measurement.new(20, 'm/s')

@api public

Calls superclass method
# File lib/unitwise/measurement.rb, line 14
def initialize(*args)
  super(*args)
  terms
end

Public Instance Methods

*(other) click to toggle source

Multiply this measurement by a number or another measurement @param other [Numeric, Unitwise::Measurement] @example

measurent * 5
measurement * some_other_measurement

@api public

# File lib/unitwise/measurement.rb, line 41
def *(other)
  operate(:*, other) ||
    fail(TypeError, "Can't multiply #{self} by #{other}.")
end
**(other) click to toggle source

Raise a measurement to a numeric power. @param number [Numeric] @example

measurement ** 2

@api public

# File lib/unitwise/measurement.rb, line 80
def **(other)
  if other.is_a?(Numeric)
    new(value ** other, unit ** other)
  else
    fail TypeError, "Can't raise #{self} to #{other} power."
  end
end
+(other) click to toggle source

Add another measurement to this unit. Units must be compatible. @param other [Unitwise::Measurement] @example

measurement + some_other_measurement

@api public

# File lib/unitwise/measurement.rb, line 61
def +(other)
  combine(:+, other) || fail(TypeError, "Can't add #{other} to #{self}.")
end
-(other) click to toggle source

Subtract another measurement from this unit. Units must be compatible. @param (see +) @example

measurement - some_other_measurement

@api public

# File lib/unitwise/measurement.rb, line 70
def -(other)
  combine(:-, other) ||
    fail(TypeError, "Can't subtract #{other} from #{self}.")
end
/(other) click to toggle source

Divide this measurement by a number or another measurement @param (see *) @example

measurement / 2
measurement / some_other_measurement

@api public

# File lib/unitwise/measurement.rb, line 52
def /(other)
  operate(:/, other) || fail(TypeError, "Can't divide #{self} by #{other}")
end
coerce(other) click to toggle source

Coerce a numeric to a a measurement for mathematical operations @param other [Numeric] @example

2.5 * measurement
4 / measurement

@api public

# File lib/unitwise/measurement.rb, line 102
def coerce(other)
  case other
  when Numeric
    return self.class.new(other, '1'), self
  else
    fail TypeError, "#{self.class} can't be coerced into #{other.class}"
  end
end
convert_to(other_unit) click to toggle source

Convert this measurement to a compatible unit. @param other_unit [String, Measurement::Unit] Either a string expression or a Measurement::Unit @example

measurement1.convert_to('foot')
measurement2.convert_to('kilogram')

@api public

# File lib/unitwise/measurement.rb, line 26
def convert_to(other_unit)
  other_unit = Unit.new(other_unit)
  if compatible_with?(other_unit)
    new(converted_value(other_unit), other_unit)
  else
    fail ConversionError, "Can't convert #{self} to #{other_unit}."
  end
end
method_missing(meth, *args, &block) click to toggle source

Will attempt to convert to a unit by method name. @example

measurement.to_foot # => <Unitwise::Measurement 4 foot>

@api semipublic

Calls superclass method
# File lib/unitwise/measurement.rb, line 139
def method_missing(meth, *args, &block)
  if args.empty? && !block_given? && (match = /\Ato_(\w+)\Z/.match(meth.to_s))
    begin
      convert_to(match[1])
    rescue ExpressionError
      super(meth, *args, &block)
    end
  else
    super(meth, *args, &block)
  end
end
round(digits = nil) click to toggle source

Round the measurement value. Delegates to the value's class. @return [Integer, Float] @api public

# File lib/unitwise/measurement.rb, line 91
def round(digits = nil)
  rounded_value = digits ? value.round(digits) : value.round
  self.class.new(rounded_value, unit)
end
to_f() click to toggle source

Convert a measurement to a Float. @example

measurement.to_f # => 4.25

@api public

# File lib/unitwise/measurement.rb, line 123
def to_f
  Float(value)
end
to_i() click to toggle source

Convert a measurement to an Integer. @example

measurement.to_i # => 4

@api public

# File lib/unitwise/measurement.rb, line 115
def to_i
  Integer(value)
end
to_r() click to toggle source

Convert a measurement to a Rational. @example

measurement.to_r # => (17/4)

@api public

# File lib/unitwise/measurement.rb, line 131
def to_r
  Number.rationalize(value)
end

Private Instance Methods

combine(operator, other) click to toggle source

Add or subtract other unit @api private

# File lib/unitwise/measurement.rb, line 171
def combine(operator, other)
  if other.respond_to?(:composition) && compatible_with?(other)
    new(value.send(operator, other.convert_to(unit).value), unit)
  end
end
converted_value(other_unit) click to toggle source

Determine value of the unit after conversion to another unit @api private

# File lib/unitwise/measurement.rb, line 161
def converted_value(other_unit)
  if other_unit.special?
    other_unit.magnitude scalar
  else
    scalar / other_unit.scalar
  end
end
new(*args) click to toggle source

Helper method to create a new instance from this instance @api private

# File lib/unitwise/measurement.rb, line 155
def new(*args)
  self.class.new(*args)
end
operate(operator, other) click to toggle source

Multiply or divide other unit @api private

# File lib/unitwise/measurement.rb, line 179
def operate(operator, other)
  if other.is_a?(Numeric)
    new(value.send(operator, other), unit)
  elsif other.respond_to?(:composition)
    if compatible_with?(other)
      converted = other.convert_to(unit)
      new(value.send(operator, converted.value),
          unit.send(operator, converted.unit))
    else
      new(value.send(operator, other.value),
          unit.send(operator, other.unit))
    end
  end
end