Module: SY::Unit

Includes:
NameMagic
Defined in:
lib/sy/unit.rb

Overview

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

Constant Summary collapse

PROTECTED_NAMES =
[ "kilogram" ]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#abbreviationObject Also known as: short

Unlike ordinary magnitudes, units can have names and abbreviations.



161
162
163
# File 'lib/sy/unit.rb', line 161

def abbreviation
  @abbreviation
end

#warnsObject Also known as: warns?

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



167
168
169
# File 'lib/sy/unit.rb', line 167

def warns
  @warns
end

Class Method Details

.abbreviationsObject

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



139
140
141
142
# File 'lib/sy/unit.rb', line 139

def abbreviations
  ii = instances
  Hash[ ii.map( &:short ).zip( ii ).select { |short, _| ! short.nil? } ]
end

.included(target) ⇒ Object

def self.instance



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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/sy/unit.rb', line 58

def self.included target
  target.class_exec do
    # Let's set up the naming hook for NameMagic:
    name_set_closure do |name, new_instance, old_name|
      

.instance(arg) ⇒ Object

Tweaking instance accessor from NameMagic to make it accept unit abbreviations and unit names regardless of capitalization



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/sy/unit.rb', line 23

def self.instance arg
  puts "SY::Unit module #instance method activated" if SY::DEBUG
  begin
    super # let's first try the original method
      .tap { puts "original #instance method provided by NameMagic succeeded" if SY::DEBUG }
  rescue NameError               # if we fail...
    puts "original #instance method provided by NameMagic returned NameError" if SY::DEBUG
    begin # second in order, let's try whether it's an abbreviation
      puts "trying whether the argument is an abbreviation" if SY::DEBUG
      rslt = instances.find { |unit_inst|
        if unit_inst.abbreviation then
          if unit_inst.abbreviation.to_s == arg.to_s then
            puts "For supplied argument #{arg} (#{arg.class}), it seems that " +
              "unit #{unit_inst} of quantity #{unit_inst.quantity} has abbreviation " +
              "#{unit_inst.abbreviation} matching it." if SY::DEBUG
            true
          else
            false
          end
        end
        # inst.abbreviation.to_s == arg.to_s if inst.abbreviation
      }
      fail NameError if rslt.nil? # if nothing found, super need not be called
      super rslt
    rescue NameError, TypeError
      puts "failed, we'll now try to upcase the argument in case of all-downcase argument" if SY::DEBUG
      begin # finally, let's try upcase if we have all-downcase arg
        super arg.to_s.upcase
      rescue NameError # if not, tough luck
        raise NameError, "Unknown unit symbol: #{which}"
      end
    end
  end
end

.known_symbolsObject

Full list of known unit names and unit abbreviations.



146
147
148
# File 'lib/sy/unit.rb', line 146

def known_symbols
  instance_names + abbreviations.keys
end

.of(quantity, **nn) ⇒ Object

Constructor of units of a given quantity.



119
120
121
# File 'lib/sy/unit.rb', line 119

def of quantity, **nn
  quantity.unit **nn
end

.parse_sps_using_all_prefixes(sps) ⇒ Object

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



153
154
155
156
# File 'lib/sy/unit.rb', line 153

def parse_sps_using_all_prefixes sps
  puts "Unit about to sps parse (#{sps})" if SY::DEBUG
  SY::PREFIX_TABLE.parse_sps( sps, known_symbols )
end

.pre_included(target) ⇒ Object



9
10
11
12
13
14
15
16
17
18
# File 'lib/sy/unit.rb', line 9

def self.pre_included target
  class << target
    # Overriding this method from NameMagic mixin ensures, that all Unit
    # subclasses use common namespace (Unit), rather than each their own.
    # 
    def namespace
      SY::Unit
    end
  end
end

.standard(of: nil, **nn) ⇒ Object

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.



130
131
132
133
134
135
# File 'lib/sy/unit.rb', line 130

def standard( of: nil, **nn )
  puts "Constructing a standard unit of #{of}." if SY::DEBUG
  fail ArgumentError, ":of argument missing!" if of.nil?
  qnt = SY::Quantity.instance( of )
  nn.empty? ? qnt.standard_unit : qnt.new_standard_unit( **nn )
end

Instance Method Details

#*(other) ⇒ Object

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



227
228
229
# File 'lib/sy/unit.rb', line 227

def * other
  to_magnitude * other
end

#**(exponent) ⇒ Object

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



239
240
241
# File 'lib/sy/unit.rb', line 239

def ** exponent
  to_magnitude ** exponent
end

#+(other) ⇒ Object

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



215
216
217
# File 'lib/sy/unit.rb', line 215

def + other
  to_magnitude + other
end

#-(other) ⇒ Object

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



221
222
223
# File 'lib/sy/unit.rb', line 221

def - other
  to_magnitude - other
end

#/(other) ⇒ Object

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



233
234
235
# File 'lib/sy/unit.rb', line 233

def / other
  to_magnitude / other
end

#coerce(other) ⇒ Object

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



246
247
248
# File 'lib/sy/unit.rb', line 246

def coerce other
  to_magnitude.coerce( other )
end

#initialize(short: nil, warns: true, **nn) ⇒ Object

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.



200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/sy/unit.rb', line 200

def initialize( short: nil, warns: true, **nn )
  @abbreviation = short.to_sym if short
  @warns = warns # does this unit care about blatant name collisions?
    
  # FIXME: Here, we would have to watch out for :amount being set
  # if it is a number, amount is in standard units
  # however, if it is a magnitude, especially one of another equidimensional quantity,
  # it estableshes a relationship between this and that quantity. It means that
  # the unit amount automatically becomes ... one ... and such relationship can
  # only be established for standard quantity
  super nn
end

#inspectObject

Inspect string for the unit.



264
265
266
# File 'lib/sy/unit.rb', line 264

def inspect
  name.nil? ? inspect_when_anonymous : inspect_when_named
end

#nameObject Also known as: ɴ

Unit name. While named units are typically introduced as constants in all-upper case, their names are then presented in all-lower case.



185
186
187
188
# File 'lib/sy/unit.rb', line 185

def name
  

#quantity_by_prefix(prefix) ⇒ Object

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>



284
285
286
# File 'lib/sy/unit.rb', line 284

def quantity_by_prefix prefix
  quantity
end

#reframe(other_quantity) ⇒ Object

Reframing: Unit is converted to a magnitude before reframing.



252
253
254
# File 'lib/sy/unit.rb', line 252

def reframe other_quantity
  to_magnnitude.reframe( other_quantity )
end

#short=(unit_abbreviation) ⇒ Object

Unit abbreviation setter (alias for #abbreviation=).



178
179
180
# File 'lib/sy/unit.rb', line 178

def short= unit_abbreviation
  @abbreviation = unit_abbreviation.to_sym
end

#to_sObject

Unit as string.



258
259
260
# File 'lib/sy/unit.rb', line 258

def to_s
  name.nil? ? to_s_when_anonymous : to_s_when_named
end