Class: Dimensional::Unit
- Inherits:
-
Object
- Object
- Dimensional::Unit
- Extended by:
- Enumerable
- Defined in:
- lib/dimensional/unit.rb
Overview
A standard scale unit for measuring physical quantities. In addition to the Dimension and System attribute that are well-defined by classes above, the user-defined metric attribute is available to identify units as belonging to an arbitrary metric like length, draft or property size. Effective use of the metric attribute can simplify presentation of Measures and make parsing of user input more accurate. Reference: en.wikipedia.org/wiki/Units_of_measurement
Instance Attribute Summary collapse
-
#abbreviation ⇒ Object
readonly
Returns the value of attribute abbreviation.
-
#detector ⇒ Object
readonly
Returns the value of attribute detector.
-
#dimension ⇒ Object
readonly
Returns the value of attribute dimension.
-
#format ⇒ Object
readonly
Returns the value of attribute format.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#preference ⇒ Object
readonly
Returns the value of attribute preference.
-
#reference_factor ⇒ Object
readonly
Returns the value of attribute reference_factor.
-
#reference_units ⇒ Object
readonly
Returns the value of attribute reference_units.
-
#system ⇒ Object
readonly
Returns the value of attribute system.
Class Method Summary collapse
-
.[](dim, sys, sym) ⇒ Object
Lookup the unit by name or abbreviation, scoped by dimension and system.
- .each(&block) ⇒ Object
- .register(*args) ⇒ Object
- .reset! ⇒ Object
Instance Method Summary collapse
-
#==(other) ⇒ Object
Equality is determined by equality of value-ish attributes.
-
#base ⇒ Object
Returns the unit or array of units on which this unit’s scale is ultimately based.
-
#base? ⇒ Boolean
If no reference was provided during initialization, this unit must itself be a base unit.
- #commensurable?(other) ⇒ Boolean
-
#convert(other) ⇒ Object
Returns the conversion factor to convert to the other unit.
-
#eql?(other) ⇒ Boolean
Hashing collisions are desired when we have same identity-defining attributes.
-
#factor ⇒ Object
The conversion factor relative to the base unit.
-
#hash ⇒ Object
This is pretty lame, but the expected usage means we shouldn’t get penalized.
-
#initialize(name, system, dimension, options = {}) ⇒ Unit
constructor
A new instance of Unit.
- #inspect ⇒ Object
- #to_s ⇒ Object
- #validate ⇒ Object
Constructor Details
#initialize(name, system, dimension, options = {}) ⇒ Unit
Returns a new instance of Unit.
48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/dimensional/unit.rb', line 48 def initialize(name, system, dimension, = {}) @name = name.to_s @system = system @dimension = dimension @reference_factor = [:reference_factor] || Rational(1,1) @reference_units = [:reference_units] || {} @abbreviation = [:abbreviation] @detector = [:detector] || /\A#{[name, abbreviation].compact.join('|')}\Z/ @format = [:format] || "%s %U" @preference = [:preference] || 0 validate end |
Instance Attribute Details
#abbreviation ⇒ Object (readonly)
Returns the value of attribute abbreviation.
43 44 45 |
# File 'lib/dimensional/unit.rb', line 43 def abbreviation @abbreviation end |
#detector ⇒ Object (readonly)
Returns the value of attribute detector.
46 47 48 |
# File 'lib/dimensional/unit.rb', line 46 def detector @detector end |
#dimension ⇒ Object (readonly)
Returns the value of attribute dimension.
44 45 46 |
# File 'lib/dimensional/unit.rb', line 44 def dimension @dimension end |
#format ⇒ Object (readonly)
Returns the value of attribute format.
46 47 48 |
# File 'lib/dimensional/unit.rb', line 46 def format @format end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
43 44 45 |
# File 'lib/dimensional/unit.rb', line 43 def name @name end |
#preference ⇒ Object (readonly)
Returns the value of attribute preference.
46 47 48 |
# File 'lib/dimensional/unit.rb', line 46 def preference @preference end |
#reference_factor ⇒ Object (readonly)
Returns the value of attribute reference_factor.
45 46 47 |
# File 'lib/dimensional/unit.rb', line 45 def reference_factor @reference_factor end |
#reference_units ⇒ Object (readonly)
Returns the value of attribute reference_units.
45 46 47 |
# File 'lib/dimensional/unit.rb', line 45 def reference_units @reference_units end |
#system ⇒ Object (readonly)
Returns the value of attribute system.
44 45 46 |
# File 'lib/dimensional/unit.rb', line 44 def system @system end |
Class Method Details
.[](dim, sys, sym) ⇒ Object
Lookup the unit by name or abbreviation, scoped by dimension and system
30 31 32 33 34 35 36 37 |
# File 'lib/dimensional/unit.rb', line 30 def self.[](dim, sys, sym) dim = Dimension[dim] unless dim.kind_of?(Dimension) sys = System[sys] unless sys.kind_of?(System) sym = sym.to_sym us = @store.select{|u| u.dimension == dim}.select{|u| u.system == sys} u = us.detect{|u| sym == u.name.to_sym || (u.abbreviation && sym == u.abbreviation.to_sym)} u || (raise ArgumentError, "Can't find unit: #{dim}, #{sys}, #{sym}") end |
.each(&block) ⇒ Object
18 19 20 |
# File 'lib/dimensional/unit.rb', line 18 def self.each(&block) @store.each(&block) end |
.register(*args) ⇒ Object
22 23 24 25 26 27 |
# File 'lib/dimensional/unit.rb', line 22 def self.register(*args) u = new(*args) raise "Namespace collision: #{u.inspect}" if @store.include?(u) @store << u u end |
.reset! ⇒ Object
39 40 41 |
# File 'lib/dimensional/unit.rb', line 39 def self.reset! @store.clear end |
Instance Method Details
#==(other) ⇒ Object
Equality is determined by equality of value-ish attributes. Specifically, equal factors relative to the same base.
101 102 103 |
# File 'lib/dimensional/unit.rb', line 101 def ==(other) (other.base == self.base) && other.factor == self.factor end |
#base ⇒ Object
Returns the unit or array of units on which this unit’s scale is ultimately based. The technique used is to multiply the bases’ exponents by our exponent and then consolidate resulting common bases by adding their exponents.
76 77 78 79 80 81 82 |
# File 'lib/dimensional/unit.rb', line 76 def base return {self => Rational(1,1)} if base? @base ||= reference_units.inject({}) do |summary0, (ru0, exp0)| t = ru0.base.inject({}){|summary1, (ru1, exp1)| summary1[ru1] = exp1 * exp0;summary1} summary0.merge(t) {|ru, expa, expb| expa + expb} end end |
#base? ⇒ Boolean
If no reference was provided during initialization, this unit must itself be a base unit.
69 70 71 |
# File 'lib/dimensional/unit.rb', line 69 def base? reference_units.empty? end |
#commensurable?(other) ⇒ Boolean
96 97 98 |
# File 'lib/dimensional/unit.rb', line 96 def commensurable?(other) dimension == other.dimension end |
#convert(other) ⇒ Object
Returns the conversion factor to convert to the other unit
90 91 92 93 94 |
# File 'lib/dimensional/unit.rb', line 90 def convert(other) raise "Units #{self} and #{other} are not commensurable" unless commensurable?(other) return Rational(1,1) if self == other self.factor / other.factor end |
#eql?(other) ⇒ Boolean
Hashing collisions are desired when we have same identity-defining attributes.
106 107 108 |
# File 'lib/dimensional/unit.rb', line 106 def eql?(other) other.kind_of?(self.class) && other.dimension.eql?(self.dimension) && other.system.eql?(self.system) && other.name.eql?(self.name) end |
#factor ⇒ Object
The conversion factor relative to the base unit.
85 86 87 |
# File 'lib/dimensional/unit.rb', line 85 def factor @factor ||= reference_factor * reference_units.inject(Rational(1,1)){|f, (ru, exp)| f * (ru.factor**exp)} end |
#hash ⇒ Object
This is pretty lame, but the expected usage means we shouldn’t get penalized
111 112 113 |
# File 'lib/dimensional/unit.rb', line 111 def hash [self.class, dimension, system, name].hash end |
#inspect ⇒ Object
119 120 121 |
# File 'lib/dimensional/unit.rb', line 119 def inspect "#<#{self.class.inspect}: #{dimension.to_s}:#{system.to_s}:#{to_s}>" end |
#to_s ⇒ Object
115 116 117 |
# File 'lib/dimensional/unit.rb', line 115 def to_s name rescue super end |
#validate ⇒ Object
61 62 63 64 65 66 |
# File 'lib/dimensional/unit.rb', line 61 def validate return "Reference factor must be numeric: #{@reference_factor}." unless factor.kind_of?(Numeric) return "Reference units must all be units: #{@reference_units}." unless reference_units.all?{|u, exp| u.kind_of?(Dimensional::Unit)} return "Reference exponents must all be rationals: #{@reference_units}." unless reference_units.all?{|u, exp| exp.kind_of?(Rational)} return "Preference must be numeric: #{@preference}." unless preference.kind_of?(Numeric) end |