ruby-measurement 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## ruby-measurement 1.2.0 (Mar 16, 2013)
2
+
3
+ * Implement `String#to_measurement`, `String#to_unit`,
4
+ `Symbol#to_unit`, and `Numeric#to_measurement`. *Matt Huggins*
5
+
1
6
  ## ruby-measurement 1.1.0 (Feb 6, 2013)
2
7
 
3
8
  * Move unit definition logic into `Unit` class. *Matt Huggins*
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Measurement
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/mhuggins/ruby-measurement.png)](http://travis-ci.org/mhuggins/ruby-measurement)
4
+ [![Code Climate](https://codeclimate.com/github/mhuggins/ruby-measurement.png)](https://codeclimate.com/github/mhuggins/ruby-measurement)
4
5
 
5
6
  [ruby-measurement](https://github.com/mhuggins/ruby-measurement) is a simple
6
7
  Ruby gem for calculating and converting units of measure.
@@ -23,60 +24,79 @@ Or install it yourself as:
23
24
 
24
25
  The `Measurement` class is responsible for parsing strings to determine the
25
26
  quantity entered as well as the unit of measure. This can be done through the
26
- `parse` method.
27
+ `parse` method, which returns a `Measurement` object.
27
28
 
28
- Measurement.parse('3 feet') # => 3.0 ft.
29
- Measurement.parse('25 fl oz') # => 25.0 fl. oz.
30
- Measurement.parse('12 tonnes') # => 12.0 t
31
- Measurement.parse('25 "') # => 25.0 in.
29
+ Measurement.parse('3 feet') # => 3.0 ft.
30
+ Measurement.parse('25 fl oz') # => 25.0 fl. oz.
31
+ Measurement.parse('12 tonnes') # => 12.0 t
32
+ Measurement.parse('25 "') # => 25.0 in.
32
33
 
33
- The object returned by `Measurement.parse` is of type `Measurement`.
34
+ A measurement includes both a quantity and a unit. Refer to the "Units"
35
+ section below for more details on how to interact with a unit.
34
36
 
35
- m = Measurement.parse('12 yd') # => 12.0 yd.
36
- Measurement.quantity # => 12.0
37
- Measurement.unit # => yd.
37
+ measurement = Measurement.parse('12 yd') # => 12.0 yd.
38
+ measurement.quantity # => 12.0
39
+ measurement.unit # => yd.
38
40
 
39
- The object returned by `Measurement#unit` is of type `Measurement::Unit`.
41
+ The `String` and `Numeric` classes have also been extended to simplify the
42
+ parsing of measurement values.
40
43
 
41
- u = Measurement.unit # => yd.
42
- u.name # => "yd."
43
- u.aliases # => ["yd.", "yd", "yard", "yards"]
44
+ '12 yd'.to_measurement # => 12.0 yd.
45
+ 20.to_measurement # => 20.0 count
44
46
 
45
- ## Converting units
47
+ ### Units
48
+
49
+ The `Measurement::Unit` class is used to represent the units for a measurement.
50
+ Predefined units can be looked up via `Measurement::Unit[]`.
51
+
52
+ unit = Measurement::Unit[:dozen] # => doz
53
+
54
+ Similarly, the `String#to_unit` and `Symbol#to_unit` method can be used to
55
+ accomplish the same thing.
56
+
57
+ unit = 'dozen'.to_unit # => doz
58
+ unit = :dozen.to_unit # => doz
59
+
60
+ Units provide access to their names and aliases.
61
+
62
+ unit.name # => "yd."
63
+ unit.aliases # => ["yd.", "yd", "yard", "yards"]
64
+
65
+ ### Converting units
46
66
 
47
67
  This gem allows you to convert among compatible units as long as a conversion
48
68
  has been supplied when defining a unit. The default supplied units include
49
69
  conversions among the same unit types (e.g.: converting feet to yards or meters
50
70
  to kilometers).
51
71
 
52
- m = Measurement.parse('3 feet') # => 3.0 ft.
53
- m.convert_to(:yards) # => 1.0 yd.
54
- m.convert_to(:in) # => 36.0 in.
55
- m.convert_to(:inches) # => 36.0 in.
72
+ measurement = Measurement.parse('3 feet') # => 3.0 ft.
73
+ measurement.convert_to(:yards) # => 1.0 yd.
74
+ measurement.convert_to(:in) # => 36.0 in.
75
+ measurement.convert_to(:inches) # => 36.0 in.
56
76
 
57
77
  NOTE: Converting between metric and U.S. customary systems is currently not
58
78
  included by default. It is intended to be shipped in a future release.
59
79
 
60
- ## Calculations
80
+ ### Calculations
61
81
 
62
82
  This gem allows you to add, subtract, multiply, or divide measurements that can
63
83
  be converted into one-another.
64
84
 
65
- m1 = Measurement.parse('3 feet') # => 3.0 ft.
66
- m2 = Measurement.parse('6 inch') # => 6.0 in.
67
- m1 + m2 # => 3.5 ft.
85
+ measurement1 = Measurement.parse('3 feet') # => 3.0 ft.
86
+ measurement2 = Measurement.parse('6 inch') # => 6.0 in.
87
+ measurement1 + measurement2 # => 3.5 ft.
68
88
 
69
89
  Additionally, measurements can have basic math operations performed using basic
70
90
  numeric values.
71
91
 
72
- m = Measurement.parse('2 yards') # => 2.0 yd.
73
- m * 6 # => 12.0 yd.
74
- m / 5 # => 0.4 yd.
75
- m + 3 # => 5.0 yd.
76
- m - 1 # => 1.0 yd.
77
- m ** 2 # => 4.0 yd.
92
+ measurement = Measurement.parse('2 yards') # => 2.0 yd.
93
+ measurement * 6 # => 12.0 yd.
94
+ measurement / 5 # => 0.4 yd.
95
+ measurement + 3 # => 5.0 yd.
96
+ measurement - 1 # => 1.0 yd.
97
+ measurement ** 2 # => 4.0 yd.
78
98
 
79
- ## Specifying units
99
+ ### Specifying units
80
100
 
81
101
  By default, ruby-measurement ships with common areas, lengths, volumes, and
82
102
  weights/masses for the metric and U.S. customary systems. This happens
@@ -112,7 +132,7 @@ system.
112
132
  require 'ruby-measurement/definitions/us_customary/volume'
113
133
  require 'ruby-measurement/definitions/us_customary/weight'
114
134
 
115
- ## Defining custom units & conversions
135
+ ### Defining custom units & conversions
116
136
 
117
137
  This gem also enabled you to define units of measure that aren't included by
118
138
  default.
@@ -138,9 +158,9 @@ default.
138
158
  Note that the first value passed to `Measurement.define` is the unit format
139
159
  that will be used when displaying a measurement.
140
160
 
141
- Measurement.parse('3 yr') # => 3.0 yr
142
- Measurement.parse('3 year') # => 3.0 yr
143
- Measurement.parse('3 years') # => 3.0 yr
161
+ Measurement.parse('3 yr') # => 3.0 yr
162
+ Measurement.parse('3 year') # => 3.0 yr
163
+ Measurement.parse('3 years') # => 3.0 yr
144
164
 
145
165
  ## Contributing
146
166
 
@@ -1,3 +1,4 @@
1
1
  require 'ruby-measurement/version'
2
+ require 'ruby-measurement/core_ext'
2
3
  require 'ruby-measurement/measurement'
3
4
  require 'ruby-measurement/definitions'
@@ -0,0 +1,3 @@
1
+ require 'ruby-measurement/core_ext/numeric'
2
+ require 'ruby-measurement/core_ext/string'
3
+ require 'ruby-measurement/core_ext/symbol'
@@ -0,0 +1,7 @@
1
+ require 'ruby-measurement/measurement'
2
+
3
+ class Numeric
4
+ def to_measurement
5
+ Measurement.new(self)
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ require 'ruby-measurement/measurement'
2
+
3
+ class String
4
+ def to_measurement
5
+ Measurement.parse(self)
6
+ end
7
+
8
+ def to_unit
9
+ Measurement::Unit[self] or raise ArgumentError, "Invalid unit: #{self}"
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ require 'ruby-measurement/unit'
2
+
3
+ class Symbol
4
+ def to_unit
5
+ Measurement::Unit[self] or raise ArgumentError, "Invalid unit: #{self}"
6
+ end
7
+ end
@@ -29,64 +29,23 @@ class Measurement
29
29
  "#{quantity} #{unit}"
30
30
  end
31
31
 
32
- def +(obj)
33
- case obj
34
- when Numeric
35
- self.class.new(quantity + obj.to_f, unit)
36
- when self.class
37
- if obj.unit == unit
38
- self.class.new(quantity + obj.quantity, unit)
39
- else
40
- self + obj.convert_to(unit)
41
- end
42
- else
43
- raise ArgumentError, "Invalid arithmetic: #{self} + #{obj}"
44
- end
45
- end
46
-
47
- def -(obj)
48
- case obj
49
- when Numeric
50
- self.class.new(quantity - obj.to_f, unit)
51
- when self.class
52
- if obj.unit == unit
53
- self.class.new(quantity - obj.quantity, unit)
54
- else
55
- self - obj.convert_to(unit)
32
+ %w(+ - * /).each do |operator|
33
+ class_eval <<-END, __FILE__, __LINE__ + 1
34
+ def #{operator}(obj)
35
+ case obj
36
+ when Numeric
37
+ self.class.new(quantity #{operator} obj.to_f, unit)
38
+ when self.class
39
+ if obj.unit == unit
40
+ self.class.new(quantity #{operator} obj.quantity, unit)
41
+ else
42
+ self #{operator} obj.convert_to(unit)
43
+ end
44
+ else
45
+ raise ArgumentError, "Invalid arithmetic: \#{self} #{operator} \#{obj}"
46
+ end
56
47
  end
57
- else
58
- raise ArgumentError, "Invalid arithmetic: #{self} - #{obj}"
59
- end
60
- end
61
-
62
- def *(obj)
63
- case obj
64
- when Numeric
65
- self.class.new(quantity * obj.to_f, unit)
66
- when self.class
67
- if obj.unit == unit
68
- self.class.new(quantity * obj.quantity, unit)
69
- else
70
- self * obj.convert_to(unit)
71
- end
72
- else
73
- raise ArgumentError, "Invalid arithmetic: #{self} * #{obj}"
74
- end
75
- end
76
-
77
- def /(obj)
78
- case obj
79
- when Numeric
80
- self.class.new(quantity / obj.to_f, unit)
81
- when self.class
82
- if obj.unit == unit
83
- self.class.new(quantity / obj.quantity, unit)
84
- else
85
- self / obj.convert_to(unit)
86
- end
87
- else
88
- raise ArgumentError, "Invalid arithmetic: #{self} / #{obj}"
89
- end
48
+ END
90
49
  end
91
50
 
92
51
  def **(obj)
@@ -131,7 +90,7 @@ class Measurement
131
90
  quantity = whole.to_f
132
91
  elsif str =~ RATIONAL_REGEX
133
92
  whole, _, numerator, denominator, unit_name = str.scan(RATIONAL_REGEX).first
134
-
93
+
135
94
  if numerator && denominator
136
95
  numerator = numerator.to_f + (denominator.to_f * whole.to_f)
137
96
  denominator = denominator.to_f
@@ -154,6 +113,8 @@ class Measurement
154
113
  Unit.define(unit_name, &block)
155
114
  end
156
115
 
116
+ private
117
+
157
118
  define(:count) do |unit|
158
119
  unit.convert_to(:dozen) { |value| value / 12.0 }
159
120
  end
@@ -1,3 +1,3 @@
1
1
  class Measurement
2
- VERSION = '1.1.0'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Numeric do
4
+ describe '#to_measurement' do
5
+ subject { 20 }
6
+ specify { subject.to_measurement.should eq Measurement.new(20) }
7
+ end
8
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe String do
4
+ describe '#to_measurement' do
5
+ describe 'with valid quantity' do
6
+ subject { '3' }
7
+ specify { subject.to_measurement.should eq Measurement.new(3) }
8
+ end
9
+
10
+ describe 'with valid quantity and unit' do
11
+ subject { '3 dozen' }
12
+ specify { subject.to_measurement.should eq Measurement.new(3, :dozen) }
13
+ end
14
+
15
+ describe 'with valid quantity and invalid unit' do
16
+ subject { '3 people' }
17
+ specify { expect { subject.to_measurement }.to raise_error }
18
+ end
19
+
20
+ describe 'with invalid input' do
21
+ subject { 'foobar' }
22
+ specify { expect { subject.to_measurement }.to raise_error }
23
+ end
24
+ end
25
+
26
+ describe '#to_unit' do
27
+ describe 'with valid unit' do
28
+ subject { 'dozen' }
29
+ specify { subject.to_unit.should eq Measurement::Unit[:dozen] }
30
+ end
31
+
32
+ describe 'with invalid unit' do
33
+ subject { 'person' }
34
+ specify { expect { subject.to_unit }.to raise_error }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Symbol do
4
+ describe '#to_unit' do
5
+ describe 'with valid unit' do
6
+ subject { :dozen }
7
+ specify { subject.to_unit.should eq Measurement::Unit[:dozen] }
8
+ end
9
+
10
+ describe 'with invalid unit' do
11
+ subject { :person }
12
+ specify { expect { subject.to_unit }.to raise_error }
13
+ end
14
+ end
15
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-measurement
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-06 00:00:00.000000000 Z
12
+ date: 2013-03-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &2152673660 !ruby/object:Gem::Requirement
16
+ requirement: &2160834380 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2152673660
24
+ version_requirements: *2160834380
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &2152672480 !ruby/object:Gem::Requirement
27
+ requirement: &2160833960 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2152672480
35
+ version_requirements: *2160833960
36
36
  description: Simple gem for calculating and converting measurements
37
37
  email: matt.huggins@gmail.com
38
38
  executables: []
@@ -47,6 +47,10 @@ files:
47
47
  - README.md
48
48
  - Rakefile
49
49
  - lib/ruby-measurement.rb
50
+ - lib/ruby-measurement/core_ext.rb
51
+ - lib/ruby-measurement/core_ext/numeric.rb
52
+ - lib/ruby-measurement/core_ext/string.rb
53
+ - lib/ruby-measurement/core_ext/symbol.rb
50
54
  - lib/ruby-measurement/definitions.rb
51
55
  - lib/ruby-measurement/definitions/metric.rb
52
56
  - lib/ruby-measurement/definitions/metric/area.rb
@@ -64,6 +68,9 @@ files:
64
68
  - lib/ruby-measurement/unit.rb
65
69
  - lib/ruby-measurement/version.rb
66
70
  - ruby-measurement.gemspec
71
+ - spec/ruby-measurement/core_ext/numeric_spec.rb
72
+ - spec/ruby-measurement/core_ext/string_spec.rb
73
+ - spec/ruby-measurement/core_ext/symbol_spec.rb
67
74
  - spec/ruby-measurement/definitions/metric/area_spec.rb
68
75
  - spec/ruby-measurement/definitions/metric/capacity_spec.rb
69
76
  - spec/ruby-measurement/definitions/metric/length_spec.rb
@@ -105,6 +112,9 @@ signing_key:
105
112
  specification_version: 3
106
113
  summary: Simple gem for calculating and converting measurements
107
114
  test_files:
115
+ - spec/ruby-measurement/core_ext/numeric_spec.rb
116
+ - spec/ruby-measurement/core_ext/string_spec.rb
117
+ - spec/ruby-measurement/core_ext/symbol_spec.rb
108
118
  - spec/ruby-measurement/definitions/metric/area_spec.rb
109
119
  - spec/ruby-measurement/definitions/metric/capacity_spec.rb
110
120
  - spec/ruby-measurement/definitions/metric/length_spec.rb