Class: Quantify::Unit::Base
- Inherits:
-
Object
- Object
- Quantify::Unit::Base
- Extended by:
- ExtendedMethods
- Defined in:
- lib/quantify/unit/base_unit.rb
Direct Known Subclasses
Instance Attribute Summary collapse
-
#acts_as_alternative_unit ⇒ Object
Returns the value of attribute acts_as_alternative_unit.
-
#acts_as_equivalent_unit ⇒ Object
Returns the value of attribute acts_as_equivalent_unit.
-
#base_unit ⇒ Object
Returns the value of attribute base_unit.
-
#dimensions ⇒ Object
Returns the value of attribute dimensions.
-
#factor ⇒ Object
Returns the value of attribute factor.
-
#label ⇒ Object
Returns the value of attribute label.
-
#name ⇒ Object
Returns the value of attribute name.
-
#prefix ⇒ Object
Returns the value of attribute prefix.
-
#symbol ⇒ Object
Returns the value of attribute symbol.
Class Method Summary collapse
-
.configure(&block) ⇒ Object
Syntactic sugar for defining the units known to the system, enabling the required associated units to be loaded at runtime, e.g.
-
.construct(unit, &block) ⇒ Object
Define a new unit in terms of an already instantiated compound unit.
- .construct_and_load(unit, &block) ⇒ Object
- .initialize_prefixed_version(prefix, unit) ⇒ Object
-
.load(options = nil, &block) ⇒ Object
Create a new instance of self (i.e. Base or an inherited class) and load into the system of known units.
-
.prefix_and_load(prefixes, units) ⇒ Object
Mass load prefixed units.
Instance Method Summary collapse
-
#alternatives(by = nil) ⇒ Object
List the alternative units for self, i.e.
-
#canonical_label=(new_label) ⇒ Object
Set the canonical unit label - the unique unit identifier - to a new value.
-
#coerce(object) ⇒ Object
Enables shorthand for reciprocal of a unit, e.g.
-
#configure(&block) ⇒ Object
Permits a block to be used, operating on self.
-
#configure_as_canonical(&block) ⇒ Object
Similar to #configure but makes the new unit configuration the canonical unit for self.label.
-
#divide(other) ⇒ Object
(also: #/)
Divide one unit by another.
-
#has_same_identity_as?(other) ⇒ Boolean
(also: #==)
Check if unit has the identity as another, i.e.
- #has_scaling? ⇒ Boolean
-
#initialize(options = nil, &block) ⇒ Base
constructor
Create a new Unit::Base instance.
-
#is_alternative_for?(other) ⇒ Boolean
Determine if another unit is an alternative unit for self, i.e.
-
#is_base_quantity_si_unit? ⇒ Boolean
Determine if the unit is THE canonical SI unit for a base quantity (length, mass, time, etc.).
-
#is_base_unit? ⇒ Boolean
Determine if the unit represents one of the base quantities, length, mass, time, temperature, etc.
-
#is_benchmark_unit? ⇒ Boolean
Determine if the unit is one of the units against which all other units of the same physical quantity are defined.
-
#is_compound_unit? ⇒ Boolean
Determine is a unit object represents an compound unit consisting of SI or non-SI named units.
-
#is_derived_unit? ⇒ Boolean
Determine is the unit is a derived unit - that is, a unit made up of more than one of the base quantities.
- #is_dimensionless? ⇒ Boolean
-
#is_equivalent_to?(other) ⇒ Boolean
Determine if self is equivalent to another.
-
#is_non_si_unit? ⇒ Boolean
Determine is a unit object represents an NonSI named unit.
-
#is_prefixed_unit? ⇒ Boolean
Determine if the unit is a prefixed unit.
-
#is_si_unit? ⇒ Boolean
Determine is a unit object represents an SI named unit.
-
#load(&block) ⇒ Object
Load an initialized Unit into the system of known units.
-
#loaded? ⇒ Boolean
check if an object with the same label already exists.
-
#make_canonical ⇒ Object
Make self the canonical representation of the unit defined by self#label.
-
#measures ⇒ Object
Describes what the unit measures/represents.
-
#multiply(other) ⇒ Object
(also: #times, #*)
Multiply two units together.
- #pluralized_name ⇒ Object
-
#pow(power) ⇒ Object
(also: #**)
Raise a unit to a power.
-
#reciprocalize ⇒ Object
Return new unit representing the reciprocal of self, i.e.
-
#refresh_attributes ⇒ Object
Refresh the name, symbol and label attributes of self with respect to the configuration found in Quantify.use_superscript_characters?.
-
#scaling ⇒ Object
Returns the scaling factor for the unit with repsect to its SI alternative.
-
#si_unit ⇒ Object
Returns the SI unit for the same physical quantity which is represented by self, e.g.
-
#to_hash ⇒ Object
Return a hash representation of self containing each unit attribute (i.e each instance variable).
-
#unload ⇒ Object
Remove from system of known units.
- #valid? ⇒ Boolean
- #valid_descriptors? ⇒ Boolean
- #valid_dimensions? ⇒ Boolean
-
#with_prefix(name_or_symbol) ⇒ Object
Apply a prefix to self.
-
#with_prefixes(*prefixes) ⇒ Object
Return an array of new unit instances based upon self, together with the prefixes specified by
prefixes
.
Constructor Details
#initialize(options = nil, &block) ⇒ Base
Create a new Unit::Base instance.
Valid options are: :name => The unit name, e.g. :kilometre
:dimensions => The physical quantity represented
by the unit (e.g. force, mass).
This must be recognised as a member
of the Dimensions.dimensions array
:physical_quantity => Alias for :dimensions
:symbol => The unit symbol, e.g. 'kg'
:factor => The factor which relates the unit
to the SI unit for the same physical
quantity. For example the :factor for
a foot would be 0.3048, since a foot
= 0.3048 m (metre is the SI unit of
length). If no factor is set, it is
assumed to be 1 - which represents
an SI benchmark unit.
:scaling => A scaling factor, used only by NonSI
temperature units
:label => The label used by JScience for the
unit
The physical quantity option is used to locate the corresponding dimensional representation in the Dimensions class. This dimensions attribute is to provide much of the unit functionality
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/quantify/unit/base_unit.rb', line 110 def initialize(=nil,&block) @acts_as_alternative_unit = true @acts_as_equivalent_unit = false self.factor = 1.0 self.symbol = nil self.label = nil self.name = nil self.base_unit = nil self.prefix = nil if .is_a? Hash self.dimensions = [:dimensions] || [:physical_quantity] if [:dimensions] || [:physical_quantity] self.factor = [:factor] if [:factor] self.name = [:name] if [:name] self.symbol = [:symbol] if [:symbol] self.label = [:label] if [:label] end block.call(self) if block_given? valid? end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object (private)
574 575 576 577 578 579 580 581 |
# File 'lib/quantify/unit/base_unit.rb', line 574 def method_missing(method, *args, &block) if method.to_s =~ /(to_)(.*)/ && prefix = Prefix.for($2.to_sym) return self.with_prefix(prefix) elsif method.to_s =~ /(alternatives_by_)(.*)/ && self.respond_to?($2.to_sym) return self.alternatives($2.to_sym) end super end |
Instance Attribute Details
#acts_as_alternative_unit ⇒ Object
Returns the value of attribute acts_as_alternative_unit.
75 76 77 |
# File 'lib/quantify/unit/base_unit.rb', line 75 def acts_as_alternative_unit @acts_as_alternative_unit end |
#acts_as_equivalent_unit ⇒ Object
Returns the value of attribute acts_as_equivalent_unit.
75 76 77 |
# File 'lib/quantify/unit/base_unit.rb', line 75 def acts_as_equivalent_unit @acts_as_equivalent_unit end |
#base_unit ⇒ Object
Returns the value of attribute base_unit.
76 77 78 |
# File 'lib/quantify/unit/base_unit.rb', line 76 def base_unit @base_unit end |
#dimensions ⇒ Object
Returns the value of attribute dimensions.
74 75 76 |
# File 'lib/quantify/unit/base_unit.rb', line 74 def dimensions @dimensions end |
#factor ⇒ Object
Returns the value of attribute factor.
74 75 76 |
# File 'lib/quantify/unit/base_unit.rb', line 74 def factor @factor end |
#label ⇒ Object
Returns the value of attribute label.
74 75 76 |
# File 'lib/quantify/unit/base_unit.rb', line 74 def label @label end |
#name ⇒ Object
Returns the value of attribute name.
74 75 76 |
# File 'lib/quantify/unit/base_unit.rb', line 74 def name @name end |
#prefix ⇒ Object
Returns the value of attribute prefix.
76 77 78 |
# File 'lib/quantify/unit/base_unit.rb', line 76 def prefix @prefix end |
#symbol ⇒ Object
Returns the value of attribute symbol.
74 75 76 |
# File 'lib/quantify/unit/base_unit.rb', line 74 def symbol @symbol end |
Class Method Details
.configure(&block) ⇒ Object
Syntactic sugar for defining the units known to the system, enabling the required associated units to be loaded at runtime, e.g.
Unit::[Base|SI|NonSI].configure do |config|
load :name => :metre, :physical_quantity => :length
load :name => 'hectare', :physical_quantity => :area, :factor => 10000
load :name => :watt, :physical_quantity => :power, :symbol => 'W'
end
70 71 72 |
# File 'lib/quantify/unit/base_unit.rb', line 70 def self.configure(&block) class_eval(&block) if block end |
.construct(unit, &block) ⇒ Object
Define a new unit in terms of an already instantiated compound unit. This unit becomes a representation of the compound - without explicitly holding the base units, e.g.
Unit::Base.construct(Unit.m**2).name #=> "square metre"
Unit::Base.construct(Unit.m**3) do |unit|
unit.name = "metres cubed"
end.name #=> "metres cubed"
53 54 55 56 57 |
# File 'lib/quantify/unit/base_unit.rb', line 53 def self.construct(unit,&block) new_unit = self.new unit.to_hash block.call(new_unit) if block_given? return new_unit end |
.construct_and_load(unit, &block) ⇒ Object
17 18 19 |
# File 'lib/quantify/unit/base_unit.rb', line 17 def self.construct_and_load(unit,&block) self.construct(unit, &block).load end |
.initialize_prefixed_version(prefix, unit) ⇒ Object
21 22 23 24 25 26 27 |
# File 'lib/quantify/unit/base_unit.rb', line 21 def self.initialize_prefixed_version(prefix,unit) prefix, unit = Prefix.for(prefix), Unit.for(unit) raise Exceptions::InvalidArgumentError, "Prefix is not known" if prefix.nil? raise Exceptions::InvalidArgumentError, "Unit is not known" if unit.nil? raise Exceptions::InvalidArgumentError, "Cannot add prefix where one already exists: #{unit.prefix.name}" if unit.prefix self.new &self.block_for_prefixed_version(prefix,unit) end |
.load(options = nil, &block) ⇒ Object
Create a new instance of self (i.e. Base or an inherited class) and load into the system of known units. See initialize for details of options
13 14 15 |
# File 'lib/quantify/unit/base_unit.rb', line 13 def self.load(=nil,&block) self.new(,&block).load end |
.prefix_and_load(prefixes, units) ⇒ Object
Mass load prefixed units. First argument is a single or array of units. Second argument is a single or array of prefixes. All specfied units will be loaded with all specified prefixes.
33 34 35 36 37 38 39 40 41 |
# File 'lib/quantify/unit/base_unit.rb', line 33 def self.prefix_and_load(prefixes,units) [units].flatten.each do |unit| unit = Unit.for(unit) [prefixes].flatten.each do |prefix| prefixed_unit = unit.with_prefix(prefix) rescue unit prefixed_unit.load unless prefixed_unit.loaded? end end end |
Instance Method Details
#alternatives(by = nil) ⇒ Object
List the alternative units for self, i.e. the other units which share the same dimensions.
The list can be returned containing the alternative unit names, symbols or JScience labels by providing the required format as a symbolized argument.
If no format is provide, the full unit objects for all alternative units are returned within the array
411 412 413 414 415 |
# File 'lib/quantify/unit/base_unit.rb', line 411 def alternatives(by=nil) @dimensions.units(nil).reject do |unit| unit.is_equivalent_to?(self) || !unit.acts_as_alternative_unit end.map(&by).to_a end |
#canonical_label=(new_label) ⇒ Object
Set the canonical unit label - the unique unit identifier - to a new value
249 250 251 252 253 |
# File 'lib/quantify/unit/base_unit.rb', line 249 def canonical_label=(new_label) unload if loaded? self.label = new_label load end |
#coerce(object) ⇒ Object
Enables shorthand for reciprocal of a unit, e.g.
unit = Unit.m
(1/unit).symbol #=> "m^-1"
529 530 531 532 533 534 535 |
# File 'lib/quantify/unit/base_unit.rb', line 529 def coerce(object) if object.kind_of?(Numeric) && object == 1 return Unit.unity, self else raise Exceptions::InvalidArgumentError, "Cannot coerce #{self.class} into #{object.class}" end end |
#configure(&block) ⇒ Object
Permits a block to be used, operating on self. This is useful for modifying the attributes of an already instantiated unit, especially when defining units on the basis of operation on existing units for adding specific (rather than derived) names or symbols, e.g.
(Unit.pound_force/(Unit.in**2)).configure do |unit|
unit.symbol = 'psi'
unit.label = 'psi'
unit.name = 'pound per square inch'
end
206 207 208 209 |
# File 'lib/quantify/unit/base_unit.rb', line 206 def configure(&block) block.call(self) if block_given? return self if valid? end |
#configure_as_canonical(&block) ⇒ Object
Similar to #configure but makes the new unit configuration the canonical unit for self.label
214 215 216 217 218 |
# File 'lib/quantify/unit/base_unit.rb', line 214 def configure_as_canonical(&block) unload if loaded? configure(&block) if block_given? make_canonical end |
#divide(other) ⇒ Object Also known as: /
Divide one unit by another. This results in the generation of a compound unit.
In the event that the new unit represents a known unit, the non-compound representation is returned (i.e. of the SI or NonSI class).
459 460 461 462 463 464 465 466 467 468 469 |
# File 'lib/quantify/unit/base_unit.rb', line 459 def divide(other) = [] self.instance_of?(Unit::Compound) ? += @base_units : << self if other.instance_of? Unit::Compound += other.base_units.map { |base| base.index *= -1; base } else << CompoundBaseUnit.new(other,-1) end Unit::Compound.new(*) end |
#has_same_identity_as?(other) ⇒ Boolean Also known as: ==
Check if unit has the identity as another, i.e. the same label. This is used to determine if a unit with the same accessors already exists in the module variable @@units
382 383 384 |
# File 'lib/quantify/unit/base_unit.rb', line 382 def has_same_identity_as?(other) @label == other.label && !@label.nil? end |
#has_scaling? ⇒ Boolean
274 275 276 |
# File 'lib/quantify/unit/base_unit.rb', line 274 def has_scaling? scaling != 0.0 end |
#is_alternative_for?(other) ⇒ Boolean
Determine if another unit is an alternative unit for self, i.e. do the two units represent the same physical quantity. This is established by compraing their dimensions attributes. E.g.
Unit.metre.is_alternative_for? Unit.foot #=> true
Unit.metre.is_alternative_for? Unit.gram #=> false
Unit.metre.is_alternative_for? Unit.metre #=> true
397 398 399 |
# File 'lib/quantify/unit/base_unit.rb', line 397 def is_alternative_for?(other) other.dimensions == @dimensions end |
#is_base_quantity_si_unit? ⇒ Boolean
Determine if the unit is THE canonical SI unit for a base quantity (length, mass, time, etc.). This method ignores prefixed versions of SI base units, returning true only for metre, kilogram, second, Kelvin, etc.
305 306 307 |
# File 'lib/quantify/unit/base_unit.rb', line 305 def is_base_quantity_si_unit? is_si_unit? && is_base_unit? && is_benchmark_unit? end |
#is_base_unit? ⇒ Boolean
Determine if the unit represents one of the base quantities, length, mass, time, temperature, etc.
297 298 299 |
# File 'lib/quantify/unit/base_unit.rb', line 297 def is_base_unit? Dimensions::BASE_QUANTITIES.map {|base| base.remove_underscores }.include? self.measures end |
#is_benchmark_unit? ⇒ Boolean
Determine if the unit is one of the units against which all other units of the same physical quantity are defined. These units are almost entirely equivalent to the non-prefixed, SI units, but the one exception is the kilogram, which is an oddity in being THE canonical SI unit for mass, yet containing a prefix. This oddity makes this method useful/necessary.
327 328 329 |
# File 'lib/quantify/unit/base_unit.rb', line 327 def is_benchmark_unit? @factor == 1.0 end |
#is_compound_unit? ⇒ Boolean
Determine is a unit object represents an compound unit consisting of SI or non-SI named units
343 344 345 |
# File 'lib/quantify/unit/base_unit.rb', line 343 def is_compound_unit? self.is_a? Compound end |
#is_derived_unit? ⇒ Boolean
Determine is the unit is a derived unit - that is, a unit made up of more than one of the base quantities
312 313 314 |
# File 'lib/quantify/unit/base_unit.rb', line 312 def is_derived_unit? !is_base_unit? end |
#is_dimensionless? ⇒ Boolean
347 348 349 |
# File 'lib/quantify/unit/base_unit.rb', line 347 def is_dimensionless? @dimensions.is_dimensionless? end |
#is_equivalent_to?(other) ⇒ Boolean
Determine if self is equivalent to another. Equivalency is based on representing the same physical quantity (i.e. dimensions) and the same factor and scaling values.
Unit.metre.is_equivalent_to? Unit.foot #=> false
Unit.metre.is_equivalent_to? Unit.gram #=> false
Unit.metre.is_equivalent_to? Unit.metre #=> true
The base_units attr of Compound units are not compared. Neither are the names or symbols. This is because we want to recognise cases where units derived from operations and defined as compound units (therefore having compounded names and symbols) are the same as known, named units. For example, if we build a unit for energy using only SI units, we want to recognise this as a joule, rather than a kg m^2 s^-2, e.g.
(Unit.kg*Unit.m*Unit.m/Unit.s/Unit.s).is_equivalent_to? Unit.joule
#=> true
372 373 374 375 376 |
# File 'lib/quantify/unit/base_unit.rb', line 372 def is_equivalent_to?(other) [:dimensions,:factor,:scaling].all? do |attr| self.send(attr) == other.send(attr) end end |
#is_non_si_unit? ⇒ Boolean
Determine is a unit object represents an NonSI named unit
337 338 339 |
# File 'lib/quantify/unit/base_unit.rb', line 337 def is_non_si_unit? self.is_a? NonSI end |
#is_prefixed_unit? ⇒ Boolean
Determine if the unit is a prefixed unit
317 318 319 |
# File 'lib/quantify/unit/base_unit.rb', line 317 def is_prefixed_unit? self.prefix ? true : false end |
#is_si_unit? ⇒ Boolean
Determine is a unit object represents an SI named unit
332 333 334 |
# File 'lib/quantify/unit/base_unit.rb', line 332 def is_si_unit? self.is_a? SI end |
#load(&block) ⇒ Object
Load an initialized Unit into the system of known units.
If a block is given, the unit can be configured prior to loading, in a similar to way to the #configure method.
225 226 227 228 229 230 |
# File 'lib/quantify/unit/base_unit.rb', line 225 def load(&block) block.call(self) if block_given? raise Exceptions::InvalidArgumentError, "A unit with the same label: #{self.name}) already exists" if loaded? Quantify::Unit.units << self if valid? return self end |
#loaded? ⇒ Boolean
check if an object with the same label already exists
238 239 240 |
# File 'lib/quantify/unit/base_unit.rb', line 238 def loaded? Unit.units.any? { |unit| self.has_same_identity_as? unit } end |
#make_canonical ⇒ Object
Make self the canonical representation of the unit defined by self#label
243 244 245 246 |
# File 'lib/quantify/unit/base_unit.rb', line 243 def make_canonical unload if loaded? load end |
#measures ⇒ Object
286 287 288 |
# File 'lib/quantify/unit/base_unit.rb', line 286 def measures @dimensions.describe end |
#multiply(other) ⇒ Object Also known as: times, *
Multiply two units together. This results in the generation of a compound unit.
444 445 446 447 448 449 |
# File 'lib/quantify/unit/base_unit.rb', line 444 def multiply(other) = [] self.instance_of?(Unit::Compound) ? += @base_units : << self other.instance_of?(Unit::Compound) ? += other.base_units : << other Unit::Compound.new(*) end |
#pluralized_name ⇒ Object
290 291 292 |
# File 'lib/quantify/unit/base_unit.rb', line 290 def pluralized_name @name.pluralize end |
#pow(power) ⇒ Object Also known as: **
Raise a unit to a power. This results in the generation of a compound unit, e.g. m^3.
In the event that the new unit represents a known unit, the non-compound representation is returned (i.e. of the SI or NonSI class).
478 479 480 481 482 483 484 485 486 487 488 489 |
# File 'lib/quantify/unit/base_unit.rb', line 478 def pow(power) return nil if power == 0 original_unit = self.clone if power > 0 new_unit = self.clone (power - 1).times { new_unit *= original_unit } elsif power < 0 new_unit = reciprocalize ((power.abs) - 1).times { new_unit /= original_unit } end return new_unit end |
#reciprocalize ⇒ Object
Return new unit representing the reciprocal of self, i.e. 1/self
493 494 495 |
# File 'lib/quantify/unit/base_unit.rb', line 493 def reciprocalize Unit.unity / self end |
#refresh_attributes ⇒ Object
Refresh the name, symbol and label attributes of self with respect to the configuration found in Quantify.use_superscript_characters?
185 186 187 188 189 |
# File 'lib/quantify/unit/base_unit.rb', line 185 def refresh_attributes self.name = name self.symbol = symbol self.label = label end |
#scaling ⇒ Object
Returns the scaling factor for the unit with repsect to its SI alternative.
For example the scaling factor for degrees celsius is 273.15, i.e. celsius is a value of 273.15 greater than kelvin (but with no multiplicative factor).
270 271 272 |
# File 'lib/quantify/unit/base_unit.rb', line 270 def scaling @scaling || 0.0 end |
#si_unit ⇒ Object
Returns the SI unit for the same physical quantity which is represented by self, e.g.
420 421 422 |
# File 'lib/quantify/unit/base_unit.rb', line 420 def si_unit @dimensions.si_unit end |
#to_hash ⇒ Object
Return a hash representation of self containing each unit attribute (i.e each instance variable)
514 515 516 517 518 519 520 521 |
# File 'lib/quantify/unit/base_unit.rb', line 514 def to_hash hash = {} self.instance_variables.each do |var| symbol = var.to_s.gsub("@","").to_sym hash[symbol] = send symbol end return hash end |
#unload ⇒ Object
Remove from system of known units.
233 234 235 |
# File 'lib/quantify/unit/base_unit.rb', line 233 def unload Unit.unload(self.label) end |
#valid? ⇒ Boolean
424 425 426 427 |
# File 'lib/quantify/unit/base_unit.rb', line 424 def valid? return true if valid_descriptors? && valid_dimensions? raise Exceptions::InvalidArgumentError, "Unit definition must include a name, a symbol, a label and physical quantity" end |
#valid_descriptors? ⇒ Boolean
429 430 431 432 433 434 435 |
# File 'lib/quantify/unit/base_unit.rb', line 429 def valid_descriptors? return true if is_dimensionless? [:name, :symbol, :label].all? do |attr| attribute = send(attr) attribute.is_a?(String) && !attribute.empty? end end |
#valid_dimensions? ⇒ Boolean
437 438 439 |
# File 'lib/quantify/unit/base_unit.rb', line 437 def valid_dimensions? @dimensions.is_a? Dimensions end |
#with_prefix(name_or_symbol) ⇒ Object
Apply a prefix to self. Returns new unit according to the prefixed version of self, complete with modified name, symbol, factor, etc..
500 501 502 |
# File 'lib/quantify/unit/base_unit.rb', line 500 def with_prefix(name_or_symbol) self.class.initialize_prefixed_version(name_or_symbol,self) end |
#with_prefixes(*prefixes) ⇒ Object
Return an array of new unit instances based upon self, together with the prefixes specified by prefixes
507 508 509 |
# File 'lib/quantify/unit/base_unit.rb', line 507 def with_prefixes(*prefixes) [prefixes].map { |prefix| self.with_prefix(prefix) } end |