ruby-measurement 1.1.0 → 1.2.0

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.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