class Measurement

Constants

COMPLEX_REGEX
RATIONAL_REGEX
RATIOS
SCIENTIFIC_NUMBER
SCIENTIFIC_REGEX
UNIT_REGEX
VERSION

Attributes

quantity[R]
unit[R]

Public Class Methods

define(unit_name, &block) click to toggle source
# File lib/ruby-measurement/measurement.rb, line 132
def define(unit_name, &block)
  Unit.define(unit_name, &block)
end
new(quantity, unit_name = :count) click to toggle source
# File lib/ruby-measurement/measurement.rb, line 35
def initialize(quantity, unit_name = :count)
  unit = unit_name
  unit = Unit[unit_name.to_s] if unit_name.kind_of?(Symbol) || unit_name.kind_of?(String)

  raise ArgumentError, "Invalid quantity: '#{quantity}'" unless quantity.kind_of?(Numeric)
  raise ArgumentError, "Invalid unit: '#{unit_name}'" unless unit.kind_of?(Unit)

  @quantity = quantity
  @unit = unit
end
parse(str = '0') click to toggle source
# File lib/ruby-measurement/measurement.rb, line 115
def parse(str = '0')
  str = normalize(str)

  case str
    when COMPLEX_REGEX then unit_name, quantity = parse_complex(str)
    when SCIENTIFIC_REGEX then unit_name, quantity = parse_scientific(str)
    when RATIONAL_REGEX then unit_name, quantity = parse_rational(str)
    else raise ArgumentError, "Unable to parse: '#{str}'"
  end

  unit_name ||= 'count'
  unit = Unit[unit_name.strip.downcase]
  raise ArgumentError, "Invalid unit: '#{unit_name}'" unless unit

  new(quantity, unit)
end

Private Class Methods

normalize(string) click to toggle source
# File lib/ruby-measurement/measurement.rb, line 138
def normalize(string)
  string.dup.tap do |str|
    if str =~ Regexp.new(/(#{RATIOS.keys.join('|')})/)
      RATIOS.each do |search, replace|
        str.gsub!(search) { " #{replace}" }
      end
    end

    str.strip!
  end
end
parse_complex(str) click to toggle source
# File lib/ruby-measurement/measurement.rb, line 150
def parse_complex(str)
  real, imaginary, unit_name = str.scan(COMPLEX_REGEX).first
  quantity = Complex(real.to_f, imaginary.to_f).to_f
  return unit_name, quantity
end
parse_rational(str) click to toggle source
# File lib/ruby-measurement/measurement.rb, line 162
def parse_rational(str)
  whole, _, numerator, denominator, unit_name = str.scan(RATIONAL_REGEX).first

  if numerator && denominator
    numerator = numerator.to_f + (denominator.to_f * whole.to_f)
    denominator = denominator.to_f
    quantity = Rational(numerator, denominator).to_f
  else
    quantity = whole.to_f
  end

  return unit_name, quantity
end
parse_scientific(str) click to toggle source
# File lib/ruby-measurement/measurement.rb, line 156
def parse_scientific(str)
  whole, unit_name = str.scan(SCIENTIFIC_REGEX).first
  quantity = whole.to_f
  return unit_name, quantity
end

Public Instance Methods

**(obj) click to toggle source
# File lib/ruby-measurement/measurement.rb, line 73
def **(obj)
  case obj
  when Numeric
    self.class.new(quantity ** obj.to_f, unit)
  else
    raise ArgumentError, "Invalid arithmetic: #{self} ** #{obj}"
  end
end
<=>(obj) click to toggle source
# File lib/ruby-measurement/measurement.rb, line 82
def <=>(obj)
  if !obj.is_a?(self.class) || obj.unit != self.unit
    return nil
  end

  if quantity < obj.quantity
    -1
  elsif quantity > obj.quantity
    1
  else
    0
  end
end
convert_to(unit_name) click to toggle source
# File lib/ruby-measurement/measurement.rb, line 96
def convert_to(unit_name)
  unit = Unit[unit_name]
  raise ArgumentError, "Invalid unit: '#{unit_name}'" unless unit

  return dup if unit == @unit

  conversion = @unit.conversion(unit.name)
  raise ArgumentError, "Invalid conversion: '#@unit' to '#{unit.name}'" unless conversion

  self.class.new(conversion.call(@quantity), unit.name)
end
convert_to!(unit_name) click to toggle source
# File lib/ruby-measurement/measurement.rb, line 108
def convert_to!(unit_name)
  measurement = convert_to(unit_name)
  @unit, @quantity = measurement.unit, measurement.quantity
  self
end
inspect() click to toggle source
# File lib/ruby-measurement/measurement.rb, line 46
def inspect
  to_s
end
to_s() click to toggle source
# File lib/ruby-measurement/measurement.rb, line 50
def to_s
  "#{quantity} #{unit}"
end