ruby-units 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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: []