module SY::Unit

This class represents a unit of measurement – a predefined magnitude of a metrological quantity.

Constants

PROTECTED_NAMES

Attributes

abbreviation[R]

Unlike ordinary magnitudes, units can have names and abbreviations.

short[R]

Unlike ordinary magnitudes, units can have names and abbreviations.

warns[RW]

Whether the unit warns when the module in which unit method mixin is included contains blatant name collisions with this unit name/abbreviation.

warns?[RW]

Whether the unit warns when the module in which unit method mixin is included contains blatant name collisions with this unit name/abbreviation.

Public Class Methods

abbreviations() click to toggle source

Unit abbreviations as a hash of abbreviation => unit pairs.

# File lib/sy/unit.rb, line 100
def abbreviations
  ii = instances
  Hash[ ii.map( &:short ).zip( ii ).select { |short, _| ! short.nil? } ]
end
included(target) click to toggle source
# File lib/sy/unit.rb, line 30
def included target
  target.namespace = self

  name_set_hook do |name, new_instance, old_name|
    ɴ = name.to_s
    up, down = ɴ.upcase, ɴ.downcase
    msg = "Unit must be either all-upper or all-lower case (#{ɴ} given)!"
    fail NameError, msg unless ɴ == up || ɴ = down
    # Reject the names starting with a full prefix.
    pref = SY::PREFIX_TABLE.full_prefixes.find do |pref|
      down.starts_with? pref unless pref.empty?
    end
    fail NameError, "Name #{ɴ} starts with #{pref}- prefix!" unless
      SY::Unit::PROTECTED_NAMES.include? down if pref
    # Warn about the method name conflicts in the #include target module
    if new_instance.warns? then
      w = SY::ExpressibleInUnits::COLLISION_WARNING
      SY::ExpressibleInUnits.included_in.each do |modul|
        im = modul.instance_methods
        warn w % [down, modul] if im.include? down
        abbrev = new_instance.abbreviation
        warn w % [abbrev, modul] if im.include? abbrev
      end
    end
    up.to_sym
  end

  # We'll now define all the prefix methods on the target (#mili, #mega...),
  # representing multiplication by the aprropriate factor (side effect being
  # returning a non-unit magnitude). However, Unit offers the opportunity to
  # _reframe_ into another quantity, specified by #quantity_by_prefix method.
  # (This method normally returns the unit's own quantity, but can and should
  # be overriden for prefixes indicating special domain (eg. +cm+)...
  #
  SY::PREFIX_TABLE.full_prefixes.each do |pref|
    unless pref.empty?
      define_method pref do
        SY::Quantity
          .instance( quantity_by_prefix( pref ) )
          .magnitude( self * SY::PREFIX_TABLE.to_factor( pref ) )
      end
    end
  end
end
instance(arg) click to toggle source

Make Unit#instance ignore capitalization, accept abbreviations.

Calls superclass method
# File lib/sy/unit.rb, line 12
def instance arg
  begin
    super # let's first try the original method.
  rescue NameError => err # if we fail...
    begin # ... let's try the abbreviation
      super instances.find { |unit_inst|
        unit_inst.short.to_s == arg.to_s if unit_inst.short
      }.tap { |rslt| fail NameError if rslt.nil? } # fail if nothing found
    rescue NameError, TypeError
      begin # Let's to try upcase if we have all-downcase arg
        super arg.to_s.upcase
      rescue NameError # if not, tough luck
        raise NameError, "Unknown unit symbol: #{arg}"
      end
    end
  end
end
known_symbols() click to toggle source

Full list of known unit names and unit abbreviations.

# File lib/sy/unit.rb, line 107
def known_symbols
  instances.names( false ).map( &:downcase ) + abbreviations.keys
end
new( short: nil, warns: true, **nn ) click to toggle source

Constructor of units provides support for one additional named argument: :abbreviation, alias :short. (This is in addition to :name, alias :ɴ named argument provided by NameMagic.) As a general rule, only named units unit should be given abbreviations. In choosing unit names and abbreviations, ambiguity with regard to standard prefixes and abbreviations thereof should also be avoided. Another argument, :warns, Boolean, true by default, determines whether the method warns about name collisions with other methods defined where the SY::ExpressibleInUnits mixin is included.

Calls superclass method
# File lib/sy/unit.rb, line 151
def initialize( short: nil, warns: true, **nn )
  @abbreviation = short.to_sym if short
  @warns = warns # does this unit care about blatant name collisions?
  super nn
end
of(quantity, **nn) click to toggle source

Constructor of units of a given quantity.

# File lib/sy/unit.rb, line 81
def of quantity, **nn
  quantity.unit **nn
end
parse_sps_using_all_prefixes(sps) click to toggle source

Parses an SPS, curring it with known unit names and abbreviations, and all known full and short prefixes.

# File lib/sy/unit.rb, line 114
def parse_sps_using_all_prefixes sps
  SY::PREFIX_TABLE.parse_sps( sps, known_symbols )
end
standard( of: nil, **nn ) click to toggle source

Standard unit constructor. In absence of other named arguments, standard unit of the specified quantity is merely retrieved. If other named arguments than :quantity (alias :of) are supplied, they are forwarded to Quantity#new_standard_unit method, that resets the standard unit of the specified quantity. Note that :amount for standard units, if supplied, has special meaning of setting the relationship of that quantity.

# File lib/sy/unit.rb, line 92
def standard( of: nil, **nn )
  fail ArgumentError, ":of argument missing!" if of.nil?
  qnt = SY::Quantity.instance( of )
  nn.empty? ? qnt.standard_unit : qnt.new_standard_unit( **nn )
end

Public Instance Methods

*(other) click to toggle source

Multiplication: Unit is converted to a magnitude before the operation.

# File lib/sy/unit.rb, line 171
def * other
  to_magnitude * other
end
**(exponent) click to toggle source

Exponentiation: Unit is converted to a magnitude before the operation.

# File lib/sy/unit.rb, line 183
def ** exponent
  to_magnitude ** exponent
end
+(other) click to toggle source

Addition: Unit is converted to a magnitude before the operation.

# File lib/sy/unit.rb, line 159
def + other
  to_magnitude + other
end
-(other) click to toggle source

Subtraction: Unit is converted to a magnitude before the operation.

# File lib/sy/unit.rb, line 165
def - other
  to_magnitude - other
end
/(other) click to toggle source

Division: Unit is converted to a magnitude before the operation.

# File lib/sy/unit.rb, line 177
def / other
  to_magnitude / other
end
abbreviation=(unit_abbreviation) click to toggle source

Unit abbreviation setter.

# File lib/sy/unit.rb, line 132
def abbreviation= unit_abbreviation
  @abbreviation = unit_abbreviation.to_sym
end
coerce(other) click to toggle source

Coercion: Unit is converted to a magnitude before coercion is actually performed.

# File lib/sy/unit.rb, line 190
def coerce other
  to_magnitude.coerce( other )
end
inspect() click to toggle source

Inspect string for the unit.

# File lib/sy/unit.rb, line 208
def inspect
  name.nil? ? inspect_when_anonymous : inspect_when_named
end
quantity_by_prefix(prefix) click to toggle source

Some prefixes of some units are almost exclusively used in certain areas of science or engineering, and their appearance would indicate such specific quantity. By default, this method simply returns unit's own quantity unchanged. But it is expected that the method will be overriden by a singleton method in those units, which have area-specific prefixes. For example, centimetre, typical for civil engineering, could cause reframing into its own CentimetreLength quantity. Assuming METRE unit, this could be specified for example by: <tt> METRE.define_singleton_method :quantity_by_prefix do |full_prefix|

case full_prefix
when :centi then CentimetreLength
else self.quantity end

end </tt>

# File lib/sy/unit.rb, line 228
def quantity_by_prefix prefix
  quantity
end
reframe(other_quantity) click to toggle source

Reframing: Unit is converted to a magnitude before reframing.

# File lib/sy/unit.rb, line 196
def reframe other_quantity
  to_magnnitude.reframe( other_quantity )
end
short=(unit_abbreviation) click to toggle source

Unit abbreviation setter (alias for abbreviation=).

# File lib/sy/unit.rb, line 138
def short= unit_abbreviation
  @abbreviation = unit_abbreviation.to_sym
end
to_s() click to toggle source

Unit as string.

# File lib/sy/unit.rb, line 202
def to_s
  name.nil? ? to_s_when_anonymous : to_s_when_named
end

Private Instance Methods

inspect_when_anonymous() click to toggle source

Constructs inspect string when the unit is anonymous.

# File lib/sy/unit.rb, line 248
def inspect_when_anonymous
  "#<#{çς}: #{to_magnitude} >"
end
inspect_when_named() click to toggle source

Constructs inspect string when the unit is named.

# File lib/sy/unit.rb, line 254
def inspect_when_named
  "#<#{çς}: #{name} of #{quantity} >"
end
to_s_when_anonymous() click to toggle source

Constructs to_s string when the unit is anonymous.

# File lib/sy/unit.rb, line 236
def to_s_when_anonymous
  "[#{çς}: #{amount} of #{quantity}]"
end
to_s_when_named() click to toggle source

Constructs to_s string when the unit is named.

# File lib/sy/unit.rb, line 242
def to_s_when_named
  name
end
çς() click to toggle source

String describing this class.

# File lib/sy/unit.rb, line 260
def çς; "Unit" end