ruby-units 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +15 -0
- data/lib/{ruby_units.rb → ruby-units.rb} +43 -17
- data/test/{test_ruby_units.rb → test_ruby-units.rb} +128 -6
- metadata +5 -4
data/CHANGELOG
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Change Log for Ruby-units
|
2
|
+
=========================
|
3
|
+
2006-08-22 0.1.0 * Initial Release
|
4
|
+
2006-08-22 0.1.1 * Added new format option "1 mm".to_unit("in") now converts the result to the indicated units
|
5
|
+
* Fixed some naming issues so that the gem name matches the require name.
|
6
|
+
* Added CHANGELOG
|
7
|
+
* Improved test coverage (100% code coverage via RCov)
|
8
|
+
* fixed a bug that prevented units with a prefix in the denominator from converting properly
|
9
|
+
* can use .unit method on a string to create a new unit object
|
10
|
+
* can now coerce or define units from arrays, strings, numerics.
|
11
|
+
"1 mm".unit + [1, 'mm'] === "2 mm".unit
|
12
|
+
[1,'mm','s'].unit === "1 mm/s".unit
|
13
|
+
2.5.unit === "2.5".unit
|
14
|
+
* Added instructions on how to add custom units
|
15
|
+
|
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
# = Ruby Units
|
1
|
+
# = Ruby Units 0.1.1
|
3
2
|
#
|
4
3
|
# Copyright 2006 by Kevin C. Olbrich, Ph.D.
|
5
4
|
#
|
@@ -11,7 +10,7 @@
|
|
11
10
|
#
|
12
11
|
# See README for detailed usage instructions and examples
|
13
12
|
#
|
14
|
-
#
|
13
|
+
# ==Unit Definition Format
|
15
14
|
#
|
16
15
|
# '<name>' => [%w{prefered_name synonyms}, conversion_to_base, :classification, %w{<base> <units> <in> <numerator>} , %w{<base> <units> <in> <denominator>} ],
|
17
16
|
#
|
@@ -26,8 +25,14 @@
|
|
26
25
|
# This package covers nearly all SI, Imperial, and units commonly used
|
27
26
|
# in the United States. If your favorite units are not listed here, send me an email
|
28
27
|
#
|
29
|
-
#
|
30
|
-
#
|
28
|
+
# To add / override a unit definition, add a code block like this..
|
29
|
+
#
|
30
|
+
# class Unit < Numeric
|
31
|
+
# UNIT_DEFINITIONS = {
|
32
|
+
# <name>' => [%w{prefered_name synonyms}, conversion_to_base, :classification, %w{<base> <units> <in> <numerator>} , %w{<base> <units> <in> <denominator>} ]
|
33
|
+
# }
|
34
|
+
# end
|
35
|
+
# Unit.setup
|
31
36
|
class Unit < Numeric
|
32
37
|
require 'units'
|
33
38
|
# pre-generate hashes from unit definitions for performance.
|
@@ -77,14 +82,16 @@ class Unit < Numeric
|
|
77
82
|
# 8 lbs 8 oz -- recognized as 8 lbs + 8 ounces
|
78
83
|
#
|
79
84
|
def initialize(options)
|
80
|
-
|
81
|
-
|
82
|
-
|
85
|
+
case options
|
86
|
+
when String: parse(options)
|
87
|
+
when Hash:
|
83
88
|
@quantity = options[:quantity] || 1
|
84
89
|
@numerator = options[:numerator] || ["<1>"]
|
85
90
|
@denominator = options[:denominator] || []
|
91
|
+
when Array: parse("#{options[0]} #{options[1]}/#{options[2]}")
|
92
|
+
when Numeric: parse(options.to_s)
|
86
93
|
else
|
87
|
-
raise ArgumentError, "
|
94
|
+
raise ArgumentError, "Invalid Unit Format"
|
88
95
|
end
|
89
96
|
self.update_base_quantity
|
90
97
|
self.unit_signature
|
@@ -120,16 +127,16 @@ class Unit < Numeric
|
|
120
127
|
den << @@UNIT_VALUES[Regexp.escape(unit)][:denominator] if @@UNIT_VALUES[Regexp.escape(unit)] && @@UNIT_VALUES[Regexp.escape(unit)][:denominator]
|
121
128
|
end
|
122
129
|
end
|
123
|
-
|
124
130
|
@denominator.each do |unit|
|
125
|
-
if @@
|
126
|
-
q /= @@
|
131
|
+
if @@PREFIX_VALUES[Regexp.escape(unit)]
|
132
|
+
q /= @@PREFIX_VALUES[Regexp.escape(unit)]
|
127
133
|
else
|
128
134
|
q /= @@UNIT_VALUES[Regexp.escape(unit)][:quantity] if @@UNIT_VALUES[Regexp.escape(unit)]
|
129
135
|
den << @@UNIT_VALUES[Regexp.escape(unit)][:numerator] if @@UNIT_VALUES[Regexp.escape(unit)] && @@UNIT_VALUES[Regexp.escape(unit)][:numerator]
|
130
136
|
num << @@UNIT_VALUES[Regexp.escape(unit)][:denominator] if @@UNIT_VALUES[Regexp.escape(unit)] && @@UNIT_VALUES[Regexp.escape(unit)][:denominator]
|
131
137
|
end
|
132
138
|
end
|
139
|
+
|
133
140
|
num = num.flatten.compact
|
134
141
|
den = den.flatten.compact
|
135
142
|
num = ['<1>'] if num.empty?
|
@@ -497,8 +504,10 @@ class Unit < Numeric
|
|
497
504
|
case other
|
498
505
|
when Unit : [other, self]
|
499
506
|
when String : [Unit.new(other), self]
|
507
|
+
when Array: [Unit.new(other.join('*')), self]
|
508
|
+
when Numeric : [Unit.new(other.to_s), self]
|
500
509
|
else
|
501
|
-
|
510
|
+
raise ArgumentError, "Invalid Unit Definition"
|
502
511
|
end
|
503
512
|
end
|
504
513
|
|
@@ -587,10 +596,27 @@ end
|
|
587
596
|
|
588
597
|
class Object
|
589
598
|
def Unit(other)
|
590
|
-
|
599
|
+
other.to_unit
|
591
600
|
end
|
592
|
-
|
593
|
-
|
594
|
-
|
601
|
+
end
|
602
|
+
|
603
|
+
class Numeric
|
604
|
+
def to_unit(other = nil)
|
605
|
+
other ? Unit.new(self.to_s) >> other : Unit.new(self.to_s)
|
606
|
+
end
|
607
|
+
alias :unit :to_unit
|
608
|
+
end
|
609
|
+
|
610
|
+
class Array
|
611
|
+
def to_unit(other = nil)
|
612
|
+
other ? Unit.new("#{self[0]} #{self[1]}/#{self[2]}") >> other : Unit.new("#{self[0]} #{self[1]}/#{self[2]}")
|
613
|
+
end
|
614
|
+
alias :unit :to_unit
|
615
|
+
end
|
616
|
+
|
617
|
+
class String
|
618
|
+
def to_unit(other = nil)
|
619
|
+
other ? Unit.new(self) >> other : Unit.new(self)
|
595
620
|
end
|
621
|
+
alias :unit :to_unit
|
596
622
|
end
|
@@ -1,13 +1,22 @@
|
|
1
1
|
require 'test/unit'
|
2
|
-
require '
|
2
|
+
require 'ruby-units'
|
3
3
|
|
4
4
|
class Unit < Numeric
|
5
|
-
@@USER_DEFINITIONS = {'<inchworm>' => [%w{inworm inchworm}, 0.0254, :length, %w{<meter>} ]
|
5
|
+
@@USER_DEFINITIONS = {'<inchworm>' => [%w{inworm inchworm}, 0.0254, :length, %w{<meter>} ],
|
6
|
+
'<habenero>' => [%{degH}, 100, :temperature, %w{<celcius>}]}
|
6
7
|
Unit.setup
|
7
8
|
end
|
8
9
|
|
9
10
|
class TestRubyUnit < Test::Unit::TestCase
|
10
11
|
|
12
|
+
def test_clone
|
13
|
+
unit1= "1 mm".unit
|
14
|
+
unit2 = unit1.clone
|
15
|
+
assert_not_equal unit1.numerator.object_id, unit2.numerator.object_id
|
16
|
+
assert_not_equal unit1.denominator.object_id, unit2.denominator.object_id
|
17
|
+
assert unit1 === unit2
|
18
|
+
end
|
19
|
+
|
11
20
|
def test_unary_minus
|
12
21
|
unit1 = Unit.new("1 mm")
|
13
22
|
unit2 = Unit.new("-1 mm")
|
@@ -27,7 +36,9 @@ class TestRubyUnit < Test::Unit::TestCase
|
|
27
36
|
|
28
37
|
def test_to_base
|
29
38
|
unit1 = Unit.new("100 cm")
|
30
|
-
|
39
|
+
assert_in_delta 1, 0.001, unit1.to_base.quantity
|
40
|
+
unit2 = Unit("1 mm^2 ms^-2")
|
41
|
+
assert_in_delta 1, 0.001, unit2.to_base.quantity
|
31
42
|
end
|
32
43
|
|
33
44
|
def test_to_unit
|
@@ -36,6 +47,18 @@ class TestRubyUnit < Test::Unit::TestCase
|
|
36
47
|
unit2 = Unit("1 mm")
|
37
48
|
assert Unit === unit1
|
38
49
|
assert unit1 == unit2
|
50
|
+
unit1 = "2.54 cm".to_unit("in")
|
51
|
+
assert_in_delta 1, 0.001, unit1.quantity
|
52
|
+
assert_equal ['<inch>'], unit1.numerator
|
53
|
+
unit1 = "2.54 cm".unit("in")
|
54
|
+
assert_in_delta 1, 0.001, unit1.quantity
|
55
|
+
assert_equal ['<inch>'], unit1.numerator
|
56
|
+
unit1 = 1.unit
|
57
|
+
assert_in_delta 1, 0.001, unit1.quantity
|
58
|
+
assert_equal ['<1>'], unit1.numerator
|
59
|
+
unit1 = [1,'mm'].unit
|
60
|
+
assert_in_delta 1, 0.001, unit1.quantity
|
61
|
+
assert_equal ['<milli>','<meter>'], unit1.numerator
|
39
62
|
end
|
40
63
|
|
41
64
|
def test_create_unitless
|
@@ -91,6 +114,20 @@ class TestRubyUnit < Test::Unit::TestCase
|
|
91
114
|
assert_equal ['<second>','<second>'],unit1.denominator
|
92
115
|
end
|
93
116
|
|
117
|
+
def test_create_from_array
|
118
|
+
unit1 = Unit.new([1, "mm^2", "ul^2"])
|
119
|
+
assert_equal 1, unit1.to_f
|
120
|
+
assert_equal ['<milli>','<meter>','<milli>','<meter>'], unit1.numerator
|
121
|
+
assert_equal ['<micro>','<liter>','<micro>','<liter>'], unit1.denominator
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_bad_create
|
125
|
+
assert_raises(ArgumentError) { Unit.new(nil)}
|
126
|
+
assert_raises(ArgumentError) { Unit.new(true)}
|
127
|
+
assert_raises(ArgumentError) { Unit.new(false)}
|
128
|
+
assert_raises(ArgumentError) { Unit.new(/(.+)/)}
|
129
|
+
end
|
130
|
+
|
94
131
|
def test_convert
|
95
132
|
unit1 = Unit.new("1 attoparsec/microfortnight")
|
96
133
|
assert_nothing_raised {
|
@@ -115,6 +152,15 @@ class TestRubyUnit < Test::Unit::TestCase
|
|
115
152
|
assert_raises(ArgumentError) { unit3= unit1 >> 5.0}
|
116
153
|
end
|
117
154
|
|
155
|
+
def test_compare
|
156
|
+
unit1 = "1 mm".unit
|
157
|
+
unit2 = "1 mm".unit
|
158
|
+
unit3 = unit2 >> "in"
|
159
|
+
assert unit1 === unit2
|
160
|
+
assert !(unit1 === unit3)
|
161
|
+
assert unit1 === "1 mm"
|
162
|
+
end
|
163
|
+
|
118
164
|
def test_matched_units
|
119
165
|
unit1 = Unit.new("1 m*kg/s")
|
120
166
|
unit2 = Unit.new("1 in*pound/min")
|
@@ -178,6 +224,47 @@ class TestRubyUnit < Test::Unit::TestCase
|
|
178
224
|
assert_raise(ArgumentError) {(unit1+unit2).to_f}
|
179
225
|
end
|
180
226
|
|
227
|
+
def test_add_coerce
|
228
|
+
unit1 = "1 mm".unit
|
229
|
+
assert_nothing_raised {
|
230
|
+
unit2 = unit1 + "1 mm"
|
231
|
+
assert_equal "2 mm".unit, unit2
|
232
|
+
}
|
233
|
+
assert_nothing_raised {
|
234
|
+
unit2 = unit1 + [1,"mm"]
|
235
|
+
assert_equal "2 mm".unit, unit2
|
236
|
+
}
|
237
|
+
assert_nothing_raised {
|
238
|
+
unit2 = "1".unit + 1
|
239
|
+
assert_equal "2".unit, unit2
|
240
|
+
}
|
241
|
+
assert_raises(ArgumentError) {
|
242
|
+
unit2 = "1".unit + nil
|
243
|
+
}
|
244
|
+
end
|
245
|
+
|
246
|
+
def test_subtract_coerce
|
247
|
+
unit1 = "1 mm".unit
|
248
|
+
assert_nothing_raised {
|
249
|
+
unit2 = unit1 - "1 mm"
|
250
|
+
assert_equal "0 mm".unit, unit2
|
251
|
+
}
|
252
|
+
end
|
253
|
+
def test_multiply_coerce
|
254
|
+
unit1 = "1 mm".unit
|
255
|
+
assert_nothing_raised {
|
256
|
+
unit2 = unit1 * "1 mm"
|
257
|
+
assert_equal "1 mm^2".unit, unit2
|
258
|
+
}
|
259
|
+
end
|
260
|
+
def test_divide_coerce
|
261
|
+
unit1 = "1 mm".unit
|
262
|
+
assert_nothing_raised {
|
263
|
+
unit2 = unit1 / "1 mm"
|
264
|
+
assert_equal "1".unit, unit2
|
265
|
+
}
|
266
|
+
end
|
267
|
+
|
181
268
|
def test_signature #"1 m s deg K kg A mol cd byte rad
|
182
269
|
unit1 = Unit.new("1 m*s*degK*kg*A*mol*cd*byte*rad*dollar")
|
183
270
|
assert_equal unit1.signature, (0..9).inject(0) {|product, n| product + 20**n}
|
@@ -198,11 +285,11 @@ class TestRubyUnit < Test::Unit::TestCase
|
|
198
285
|
end
|
199
286
|
|
200
287
|
def test_multiply
|
201
|
-
unit1 = Unit.new("1
|
202
|
-
unit2 = Unit.new("
|
288
|
+
unit1 = Unit.new("1 m/ms")
|
289
|
+
unit2 = Unit.new("1 m/ms")
|
203
290
|
assert_nothing_raised {
|
204
291
|
unit3 = unit1 * unit2
|
205
|
-
assert_equal Unit.new("
|
292
|
+
assert_equal Unit.new("1 m^2/ms^2"), unit3
|
206
293
|
}
|
207
294
|
end
|
208
295
|
|
@@ -313,6 +400,41 @@ class TestRubyUnit < Test::Unit::TestCase
|
|
313
400
|
assert_in_delta 558.27, unit2.to_f, 0.01
|
314
401
|
unit3 = Unit.new("1 J/degC")
|
315
402
|
assert_in_delta 1, (unit3 >> "J/degK").to_f, 0.01
|
403
|
+
assert_raises(ArgumentError) {unit1 >> "degH"}
|
404
|
+
|
405
|
+
unit1 = Unit.new("98.6 degF")
|
406
|
+
unit2 = unit1 >> "degC"
|
407
|
+
assert_in_delta 37, unit2.to_f, 0.1
|
408
|
+
unit2 = unit1 >> "degK"
|
409
|
+
assert_in_delta 310.15, unit2.to_f, 0.01
|
410
|
+
unit2 = unit1 >> "degR"
|
411
|
+
assert_in_delta 558.27, unit2.to_f, 0.01
|
412
|
+
unit3 = Unit.new("1 J/degC")
|
413
|
+
assert_in_delta 1, (unit3 >> "J/degK").to_f, 0.01
|
414
|
+
assert_raises(ArgumentError) {unit1 >> "degH"}
|
415
|
+
|
416
|
+
unit1 = Unit.new("310.15 degK")
|
417
|
+
unit2 = unit1 >> "degF"
|
418
|
+
assert_in_delta 98.6, unit2.to_f, 0.1
|
419
|
+
unit2 = unit1 >> "degC"
|
420
|
+
assert_in_delta 37, unit2.to_f, 0.01
|
421
|
+
unit2 = unit1 >> "degR"
|
422
|
+
assert_in_delta 558.27, unit2.to_f, 0.01
|
423
|
+
unit3 = Unit.new("1 J/degC")
|
424
|
+
assert_in_delta 1, (unit3 >> "J/degK").to_f, 0.01
|
425
|
+
assert_raises(ArgumentError) {unit1 >> "degH"}
|
426
|
+
|
427
|
+
unit1 = Unit.new("558.27 degR")
|
428
|
+
unit2 = unit1 >> "degC"
|
429
|
+
assert_in_delta 37, unit2.to_f, 0.1
|
430
|
+
unit2 = unit1 >> "degK"
|
431
|
+
assert_in_delta 310.15, unit2.to_f, 0.01
|
432
|
+
unit2 = unit1 >> "degF"
|
433
|
+
assert_in_delta 98.6, unit2.to_f, 0.01
|
434
|
+
unit3 = Unit.new("1 J/degC")
|
435
|
+
assert_in_delta 1, (unit3 >> "J/degK").to_f, 0.01
|
436
|
+
assert_raises(ArgumentError) {unit1 >> "degH"}
|
437
|
+
assert_raises(ArgumentError) {"10 degH".unit >> "degH"}
|
316
438
|
end
|
317
439
|
|
318
440
|
def test_feet
|
metadata
CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-units
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
6
|
+
version: 0.1.1
|
7
7
|
date: 2006-08-22 00:00:00 -04:00
|
8
8
|
summary: A model that performs unit conversions and unit math
|
9
9
|
require_paths:
|
@@ -31,11 +31,12 @@ authors:
|
|
31
31
|
files:
|
32
32
|
- LICENSE
|
33
33
|
- README
|
34
|
-
-
|
34
|
+
- CHANGELOG
|
35
|
+
- lib/ruby-units.rb
|
35
36
|
- lib/units.rb
|
36
|
-
- test/
|
37
|
+
- test/test_ruby-units.rb
|
37
38
|
test_files:
|
38
|
-
- test/
|
39
|
+
- test/test_ruby-units.rb
|
39
40
|
rdoc_options: []
|
40
41
|
|
41
42
|
extra_rdoc_files: []
|