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 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
- # =Unit Definition Format
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
- # Future versions will provide a simple interface for the end-user to specify
30
- # custom units.
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
- if options.kind_of? String
81
- parse(options)
82
- elsif options.kind_of? Hash
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, "Unknown Unit Specification"
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 @@PREFIX_MAP[Regexp.escape(unit)]
126
- q /= @@PREFIX_MAP[Regexp.escape(unit)]
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
- [Unit.new(other.to_s), self]
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
- Unit.new(other.to_s)
599
+ other.to_unit
591
600
  end
592
-
593
- def to_unit
594
- Unit.new(self.to_s) unless Unit === self
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 'ruby_units'
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
- assert_equal 1.0, unit1.to_base.quantity
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 M")
202
- unit2 = Unit.new("200 g/mole")
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("200 M*g/mol"), unit3
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.0
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
- - lib/ruby_units.rb
34
+ - CHANGELOG
35
+ - lib/ruby-units.rb
35
36
  - lib/units.rb
36
- - test/test_ruby_units.rb
37
+ - test/test_ruby-units.rb
37
38
  test_files:
38
- - test/test_ruby_units.rb
39
+ - test/test_ruby-units.rb
39
40
  rdoc_options: []
40
41
 
41
42
  extra_rdoc_files: []