Class: Quantify::Quantity

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/quantify/quantity.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, unit = 'unity') ⇒ Quantity

Initialize a new Quantity object. Two arguments are required: a value and a unit. The unit can be a an instance of Unit::Base or the name, symbol or JScience label of a known (or derivable through know units and prefixes) unit



125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/quantify/quantity.rb', line 125

def initialize(value, unit = 'unity')
  if value
    @value = value.to_f
  else
    @value = nil
  end
  if unit
    @unit = Unit.for(unit)
  else
    @unit = Unit.for('unity')
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (protected)

Dynamic method for converting to another unit, e.g

2.ft.to_metre.to_s                           #=> "0.6096 m"

30.degree_celsius.to_K.to_s :name            #=> "303.15 kelvins"


411
412
413
414
415
416
417
# File 'lib/quantify/quantity.rb', line 411

def method_missing(method, *args, &block)
  if method.to_s =~ /(to_)(.*)/
    to($2)
  else
    super
  end
end

Instance Attribute Details

#unitObject

Returns the value of attribute unit.



119
120
121
# File 'lib/quantify/quantity.rb', line 119

def unit
  @unit
end

#valueObject

Returns the value of attribute value.



119
120
121
# File 'lib/quantify/quantity.rb', line 119

def value
  @value
end

Class Method Details

.auto_consolidate_units=(true_or_false) ⇒ Object



99
100
101
# File 'lib/quantify/quantity.rb', line 99

def self.auto_consolidate_units=(true_or_false)
  @auto_consolidate_units = true_or_false
end

.auto_consolidate_units?Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/quantify/quantity.rb', line 103

def self.auto_consolidate_units?
  @auto_consolidate_units.nil? ? false : @auto_consolidate_units
end

.configure(&block) ⇒ Object



95
96
97
# File 'lib/quantify/quantity.rb', line 95

def self.configure(&block)
  self.class_eval(&block) if block
end

.parse(string, options = {}) ⇒ Object

Parse a string and return a Quantity object based upon the value and subseqent unit name, symbol or JScience label. Returns an array containing quantity objects for each quantity recognised.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/quantify/quantity.rb', line 47

def self.parse(string,options={})

  return [Quantity.new(nil, nil)] unless string != nil && string.strip.length > 0

  quantities   = []
  remainder    = []
  words        = string.words

  until words.empty? do
    word = words.shift
    if word.starts_with_number?
      if (Unit::QUANTITY_REGEX).match(word)
        word, other = $1, $2
        words.unshift(other)
      end
      quantities << [word]
    else
      if quantities.empty?
        remainder << word
      else
        quantities.last << word
      end
    end
  end      

  remainders = []
  remainders << remainder.join(" ")

  quantities.map! do |words|

    value = words.shift
    string = words.join(" ")

    # Parse string for unit references
    unit, remainder = Unit.parse(string, :iterative => true, :remainder => true) 
    unit, remainder = Unit.dimensionless, string if unit.nil?
    remainders << remainder

    # Instantiate quantity using value and unit
    Quantity.new(value,unit)
      
  end.compact
  return [quantities, remainders] if options[:remainder] == true
  return quantities
rescue Quantify::Exceptions::InvalidArgumentError
  raise Quantify::Exceptions::QuantityParseError, "Cannot parse string into value and unit"
end

Instance Method Details

#<=>(other) ⇒ Object



291
292
293
294
295
296
297
298
# File 'lib/quantify/quantity.rb', line 291

def <=>(other)
  raise Exceptions::InvalidArgumentError unless other.is_a? Quantity
  raise Exceptions::InvalidArgumentError unless other.unit.is_alternative_for?(unit)
  return 0 if @value.nil? && (other.nil? || other.value.nil?)

  other = other.to @unit
  @value.to_f <=> other.value.to_f
end

#===(range) ⇒ Object



300
301
302
303
# File 'lib/quantify/quantity.rb', line 300

def ===(range)
  raise Exceptions::InvalidArgumentError unless range.is_a? Range
  range.cover? self
end

#add(other) ⇒ Object Also known as: +



230
231
232
# File 'lib/quantify/quantity.rb', line 230

def add(other)
  Quantity.new(@value,@unit).add!(other)
end

#add!(other) ⇒ Object



214
215
216
# File 'lib/quantify/quantity.rb', line 214

def add!(other)
  add_or_subtract!(:+, other)
end

#between?(min, max) ⇒ Boolean

Returns:

  • (Boolean)

Raises:

  • (NoMethodError)


305
306
307
308
# File 'lib/quantify/quantity.rb', line 305

def between?(min, max)
  raise NoMethodError if @value.nil?
  super(min,max)
end

#cancel_base_units!(*units) ⇒ Object



268
269
270
271
# File 'lib/quantify/quantity.rb', line 268

def cancel_base_units!(*units)
  @unit = @unit.cancel_base_units!(*units) if @unit.is_compound_unit?
  return self
end

#divide(other) ⇒ Object Also known as: /



246
247
248
# File 'lib/quantify/quantity.rb', line 246

def divide(other)
  Quantity.new(@value,@unit).divide!(other)
end

#divide!(other) ⇒ Object



226
227
228
# File 'lib/quantify/quantity.rb', line 226

def divide!(other)
  multiply_or_divide!(:/, other)
end

#inspectObject



165
166
167
# File 'lib/quantify/quantity.rb', line 165

def inspect
  to_s
end

#multiply(other) ⇒ Object Also known as: times, *



240
241
242
# File 'lib/quantify/quantity.rb', line 240

def multiply(other)
  Quantity.new(@value,@unit).multiply!(other)
end

#multiply!(other) ⇒ Object



222
223
224
# File 'lib/quantify/quantity.rb', line 222

def multiply!(other)
  multiply_or_divide!(:*, other)
end

#pow(power) ⇒ Object Also known as: **



251
252
253
# File 'lib/quantify/quantity.rb', line 251

def pow(power)
  Quantity.new(@value,@unit).pow!(power)
end

#pow!(power) ⇒ Object



207
208
209
210
211
212
# File 'lib/quantify/quantity.rb', line 207

def pow!(power)
  raise Exceptions::InvalidArgumentError, "Argument must be an integer" unless power.is_a? Integer
  @value = @value ** power
  @unit = @unit ** power
  return self
end

#rationalize_unitsObject



256
257
258
259
# File 'lib/quantify/quantity.rb', line 256

def rationalize_units
  return self unless @unit.is_a? Unit::Compound
  self.to @unit.clone.rationalize_base_units!
end

#rationalize_units!Object



261
262
263
264
265
266
# File 'lib/quantify/quantity.rb', line 261

def rationalize_units!
  rationalized_quantity = self.rationalize_units
  @value = rationalized_quantity.value
  @unit = rationalized_quantity.unit
  return self
end

#representsObject

Returns a description of what the quantity describes, based upon the physica quantity which is represented by the Dimensions object in the Quantity unit. e.g.

Quantity.parse("25 yr").represents            #=> :time

1.foot.represents                             #=> :length

Quantity.new(123.456, :degree_celsius).represents
                                              #=> :temperature


148
149
150
# File 'lib/quantify/quantity.rb', line 148

def represents
  @unit.measures
end

#round(decimal_places = 0) ⇒ Object

Similar to #round! but returns new Quantity instance rather than rounding in place



286
287
288
289
# File 'lib/quantify/quantity.rb', line 286

def round(decimal_places=0)
  rounded_quantity = Quantity.new @value, @unit
  rounded_quantity.round! decimal_places
end

#round!(decimal_places = 0) ⇒ Object

Round the value attribute to the specified number of decimal places. If no argument is given, the value is rounded to NO decimal places, i.e. to an integer



277
278
279
280
281
# File 'lib/quantify/quantity.rb', line 277

def round!(decimal_places=0)
  factor = ( decimal_places == 0 ? 1 : 10.0 ** decimal_places )
  @value = (@value * factor).round / factor
  self
end

#subtract(other) ⇒ Object Also known as: -



235
236
237
# File 'lib/quantify/quantity.rb', line 235

def subtract(other)
  Quantity.new(@value,@unit).subtract!(other)
end

#subtract!(other) ⇒ Object



218
219
220
# File 'lib/quantify/quantity.rb', line 218

def subtract!(other)
  add_or_subtract!(:-, other)
end

#to(new_unit) ⇒ Object

Converts self into a quantity using the unit provided as an argument. The new unit must represent the same physical quantity, i.e. have the same dimensions, e.g.

Quantity.parse("12 yd").to(:foot).to_s          #=> "36 ft"

1000.kilogram.to(:tonne).to_s                   #=> "1 t"

The method #method_missing provides some syntactic sugar for the new unit to be provided as part of the method name, based around /to_(<unit>)/, e.g.

200.cm.to_metre.to_s                   #=> "1 t"

The unit value is converted to the corresponding value for the same quantity in terms of the new unit.



185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/quantify/quantity.rb', line 185

def to(new_unit)
  new_unit = Unit.for new_unit
  if Quantity.is_basic_conversion_with_scalings?(self,new_unit)
    Quantity.new(@value,@unit).conversion_with_scalings! new_unit
  elsif self.unit.is_alternative_for? new_unit
    Quantity.new(@value,@unit).convert_to_equivalent_unit! new_unit
  elsif self.unit.is_compound_unit?
    Quantity.new(@value,@unit).convert_compound_unit_to_non_equivalent_unit! new_unit
  else
    nil # raise? or ...
  end      
end

#to_s(format = :symbol) ⇒ Object

Returns a string representation of the quantity, using the unit symbol



153
154
155
156
157
158
159
160
161
162
163
# File 'lib/quantify/quantity.rb', line 153

def to_s format=:symbol
  if format == :name
    if @value == 1 || @value == -1
      "#{@value} #{@unit.name}"
    else
      "#{@value} #{@unit.pluralized_name}"
    end
  else
    "#{@value} #{@unit.send format}"
  end
end

#to_siObject

Converts a quantity to the equivalent quantity using only SI units



199
200
201
202
203
204
205
# File 'lib/quantify/quantity.rb', line 199

def to_si
  if @unit.is_compound_unit?
    Quantity.new(@value,@unit).convert_compound_unit_to_si!
  else
    self.to(@unit.si_unit)
  end
end