Class: Measurement

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/ruby-measurement/unit.rb,
lib/ruby-measurement/version.rb,
lib/ruby-measurement/measurement.rb

Defined Under Namespace

Classes: Unit

Constant Summary collapse

VERSION =
'1.3.0'
UNIT_REGEX =
/([^\d\s\/].*)/.freeze
SCIENTIFIC_NUMBER =
/([+-]?\d*\.?\d+(?:[Ee][+-]?)?\d*)/.freeze
SCIENTIFIC_REGEX =
/\A#{SCIENTIFIC_NUMBER}\s*#{UNIT_REGEX}?\z/.freeze
RATIONAL_REGEX =
/\A([+-]?\d+\s+)?((\d+)\/(\d+))?\s*#{UNIT_REGEX}?\z/.freeze
COMPLEX_REGEX =
/\A#{SCIENTIFIC_NUMBER}?#{SCIENTIFIC_NUMBER}i\s*#{UNIT_REGEX}?\z/.freeze
RATIOS =
{
  '¼' => '1/4',
  '½' => '1/2',
  '¾' => '3/4',
  '' => '1/3',
  '' => '2/3',
  '' => '1/5',
  '' => '2/5',
  '' => '3/5',
  '' => '4/5',
  '' => '1/6',
  '' => '5/6',
  '' => '1/8',
  '' => '3/8',
  '' => '5/8',
  '' => '7/8',
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(quantity, unit_name = :count) ⇒ Measurement

Returns a new instance of Measurement.

Raises:

  • (ArgumentError)


35
36
37
38
39
40
41
42
43
44
# 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

Instance Attribute Details

#quantityObject (readonly)

Returns the value of attribute quantity.



33
34
35
# File 'lib/ruby-measurement/measurement.rb', line 33

def quantity
  @quantity
end

#unitObject (readonly)

Returns the value of attribute unit.



33
34
35
# File 'lib/ruby-measurement/measurement.rb', line 33

def unit
  @unit
end

Class Method Details

.define(unit_name, &block) ⇒ Object



132
133
134
# File 'lib/ruby-measurement/measurement.rb', line 132

def define(unit_name, &block)
  Unit.define(unit_name, &block)
end

.parse(str = '0') ⇒ Object

Raises:

  • (ArgumentError)


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# 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

Instance Method Details

#**(obj) ⇒ Object



73
74
75
76
77
78
79
80
# 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) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
# 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) ⇒ Object

Raises:

  • (ArgumentError)


96
97
98
99
100
101
102
103
104
105
106
# 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) ⇒ Object



108
109
110
111
112
# 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

#inspectObject



46
47
48
# File 'lib/ruby-measurement/measurement.rb', line 46

def inspect
  to_s
end

#to_sObject



50
51
52
# File 'lib/ruby-measurement/measurement.rb', line 50

def to_s
  "#{quantity} #{unit}"
end