height 0.0.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/.gitignore +18 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +82 -0
- data/Rakefile +2 -0
- data/height.gemspec +22 -0
- data/lib/height.rb +95 -0
- data/lib/height/core_extensions.rb +11 -0
- data/lib/height/formatters/base.rb +9 -0
- data/lib/height/formatters/imperial.rb +23 -0
- data/lib/height/formatters/metric.rb +24 -0
- data/lib/height/parser.rb +38 -0
- data/lib/height/parsers/base.rb +16 -0
- data/lib/height/parsers/imperial.rb +40 -0
- data/lib/height/parsers/metric.rb +62 -0
- data/lib/height/units/base.rb +66 -0
- data/lib/height/units/centimeters.rb +31 -0
- data/lib/height/units/feet.rb +37 -0
- data/lib/height/units/inches.rb +29 -0
- data/lib/height/units/meters.rb +38 -0
- data/lib/height/units/millimeters.rb +30 -0
- data/lib/height/version.rb +3 -0
- data/spec/core_extensions_spec.rb +15 -0
- data/spec/formatters/imperial_spec.rb +37 -0
- data/spec/formatters/metric_spec.rb +40 -0
- data/spec/height_spec.rb +66 -0
- data/spec/parser_spec.rb +10 -0
- data/spec/parsers/imperial_spec.rb +9 -0
- data/spec/parsers/metric_spec.rb +9 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/units/base_spec.rb +94 -0
- data/spec/units/centimeters_spec.rb +36 -0
- data/spec/units/feet_spec.rb +45 -0
- data/spec/units/inches_spec.rb +37 -0
- data/spec/units/meters_spec.rb +45 -0
- data/spec/units/millimeters_spec.rb +41 -0
- metadata +166 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
class Height
|
2
|
+
module Units
|
3
|
+
class Base
|
4
|
+
include Comparable
|
5
|
+
include Math
|
6
|
+
attr_reader :value
|
7
|
+
|
8
|
+
def self.round_value(value)
|
9
|
+
key = self.name.split('::').last.downcase.to_sym
|
10
|
+
|
11
|
+
precision = ::Height.units_precision[key]
|
12
|
+
|
13
|
+
value.round(precision)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(value)
|
17
|
+
@value = self.class.round_value(value)
|
18
|
+
end
|
19
|
+
|
20
|
+
def <=>(other)
|
21
|
+
value <=> other_value(other)
|
22
|
+
end
|
23
|
+
|
24
|
+
def +(other)
|
25
|
+
result = value + other_value(other)
|
26
|
+
self.class.new(result)
|
27
|
+
end
|
28
|
+
|
29
|
+
def -(other)
|
30
|
+
result = value - other_value(other)
|
31
|
+
|
32
|
+
self.class.new(result)
|
33
|
+
end
|
34
|
+
|
35
|
+
def *(other)
|
36
|
+
result = value * other_value(other)
|
37
|
+
self.class.new(result)
|
38
|
+
end
|
39
|
+
|
40
|
+
def /(other)
|
41
|
+
result = value / other_value(other)
|
42
|
+
self.class.new(result)
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_unit(klass)
|
46
|
+
class_name = klass.name.split('::').last.downcase
|
47
|
+
method = "to_#{class_name}"
|
48
|
+
send(method)
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
"%g" % ("%0.2f" % value)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def other_value(other)
|
57
|
+
if other.respond_to? :to_unit
|
58
|
+
other.to_unit(self.class).value
|
59
|
+
else
|
60
|
+
other
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Height
|
2
|
+
module Units
|
3
|
+
class Centimeters < Base
|
4
|
+
|
5
|
+
def to_millimeters
|
6
|
+
millimeters = value * MILLIMETERS_IN_CENTIMETER
|
7
|
+
Millimeters.new(millimeters)
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_centimeters
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_meters
|
15
|
+
to_millimeters.to_meters
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_inches
|
19
|
+
to_millimeters.to_inches
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_feet
|
23
|
+
to_inches.to_feet
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_s
|
27
|
+
value.round.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Height
|
2
|
+
module Units
|
3
|
+
class Feet < Base
|
4
|
+
|
5
|
+
def to_feet
|
6
|
+
self
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_inches
|
10
|
+
inches = value * Height::INCHES_IN_FOOT
|
11
|
+
Inches.new(inches)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_millimeters
|
15
|
+
to_inches.to_millimeters
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_centimeters
|
19
|
+
to_millimeters.to_centimeters
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_meters
|
23
|
+
to_millimeters.to_meters
|
24
|
+
end
|
25
|
+
|
26
|
+
def feet
|
27
|
+
self.class.new(value.floor)
|
28
|
+
end
|
29
|
+
|
30
|
+
def inches
|
31
|
+
inches = value.modulo(1) * Height::INCHES_IN_FOOT
|
32
|
+
Inches.new(inches)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Height
|
2
|
+
module Units
|
3
|
+
class Inches < Base
|
4
|
+
|
5
|
+
def to_inches
|
6
|
+
self
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_millimeters
|
10
|
+
millimeters = value * Height::MILLIMETERS_IN_INCH
|
11
|
+
Millimeters.new(millimeters)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_centimeters
|
15
|
+
to_millimeters.to_centimeters
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_meters
|
19
|
+
to_centimeters.to_meters
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_feet
|
23
|
+
feet = value / Height::INCHES_IN_FOOT.to_f
|
24
|
+
Feet.new(feet)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Height
|
2
|
+
module Units
|
3
|
+
class Meters < Base
|
4
|
+
|
5
|
+
def to_millimeters
|
6
|
+
millimeters = value * MILLIMETERS_IN_METER
|
7
|
+
Millimeters.new(millimeters)
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_centimeters
|
11
|
+
to_millimeters.to_centimeters
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_meters
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_inches
|
19
|
+
to_centimeters.to_inches
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_feet
|
23
|
+
to_inches.to_feet
|
24
|
+
end
|
25
|
+
|
26
|
+
def meters
|
27
|
+
Meters.new(value.floor)
|
28
|
+
end
|
29
|
+
|
30
|
+
def centimeters
|
31
|
+
millimeters = (to_millimeters.value - meters.to_millimeters.value)
|
32
|
+
|
33
|
+
Millimeters.new(millimeters).to_centimeters
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Height
|
2
|
+
module Units
|
3
|
+
class Millimeters < Base
|
4
|
+
|
5
|
+
def to_millimeters
|
6
|
+
self
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_centimeters
|
10
|
+
centimeters = value / Height::MILLIMETERS_IN_CENTIMETER.to_f
|
11
|
+
Centimeters.new(centimeters)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_meters
|
15
|
+
meters = value / Height::MILLIMETERS_IN_METER.to_f
|
16
|
+
Meters.new(meters)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_inches
|
20
|
+
inches = value / Height::MILLIMETERS_IN_INCH.to_f
|
21
|
+
Inches.new(inches)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_feet
|
25
|
+
to_inches.to_feet
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe Numeric do
|
5
|
+
describe '#to_height' do
|
6
|
+
it { 191.to_height.should == Height.new(191) }
|
7
|
+
it { 191.5.to_height.should == Height.new(191.5) }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe String do
|
12
|
+
describe '#to_height' do
|
13
|
+
it { '191 cm'.to_height.should == Height.new(191) }
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe Height::Formatters::Imperial do
|
3
|
+
describe '#format' do
|
4
|
+
|
5
|
+
context 'without I18n' do
|
6
|
+
it 'formats' do
|
7
|
+
units.each do |unit|
|
8
|
+
Height::Formatters::Imperial.new(unit).format.should == "6 ft 3 in"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'with I18n' do
|
14
|
+
before do
|
15
|
+
::I18n.backend.store_translations :en,
|
16
|
+
height: {
|
17
|
+
format: {
|
18
|
+
imperial: {
|
19
|
+
default: '%{feet}\' %{inches}"'
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
after do
|
26
|
+
reset_i18n
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'uses i18n formats' do
|
30
|
+
units.each do |unit|
|
31
|
+
Height::Formatters::Imperial.new(unit).format.should == '6\' 3"'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe Height::Formatters::Metric do
|
3
|
+
describe '#format' do
|
4
|
+
context 'without I18n' do
|
5
|
+
it 'formats' do
|
6
|
+
units.each do |unit|
|
7
|
+
Height::Formatters::Metric.new(unit).format.should == '1m 91cm'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'with I18n' do
|
13
|
+
before do
|
14
|
+
I18n.backend.store_translations :en,
|
15
|
+
height: {
|
16
|
+
format: {
|
17
|
+
metric: {
|
18
|
+
default: '%{meters}meters %{centimeters}centimeters',
|
19
|
+
only_meters: '%{only_meters} meters',
|
20
|
+
only_centimeters: '%{only_centimeters} centimeters'
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
after do
|
27
|
+
reset_i18n
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'formats' do
|
31
|
+
units.each do |unit|
|
32
|
+
formatter = Height::Formatters::Metric.new(unit)
|
33
|
+
formatter.format.should == '1meters 91centimeters'
|
34
|
+
formatter.format(:only_meters).should == '1.91 meters'
|
35
|
+
formatter.format(:only_centimeters).should == '191 centimeters'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/spec/height_spec.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Height do
|
4
|
+
it 'is comparable' do
|
5
|
+
Height.new(191).should > Height.new(190)
|
6
|
+
Height.new(191).should == Height.new(191)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '.system_of_units' do
|
10
|
+
it 'can be changed in Height class' do
|
11
|
+
Height.system_of_units = :imperial
|
12
|
+
Height.new(191).to_s.should == '6 ft 3 in'
|
13
|
+
Height.system_of_units = :metric
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '.units_precision' do
|
18
|
+
before do
|
19
|
+
@previous_unit_precision = Height.units_precision.dup
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'can be changed in Height class' do
|
23
|
+
Height.units_precision[:centimeters] = 2
|
24
|
+
Height.new(190.5).centimeters.should == 190.50
|
25
|
+
end
|
26
|
+
|
27
|
+
after do
|
28
|
+
Height.units_precision = @previous_unit_precision
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it '+' do
|
33
|
+
(Height.new(200) + Height.new(10)).should == Height.new(210)
|
34
|
+
end
|
35
|
+
|
36
|
+
it '-' do
|
37
|
+
(Height.new(200) - Height.new(10)).should == Height.new(190)
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#initialize' do
|
41
|
+
it 'accepts Height::Units' do
|
42
|
+
centimeters = Height::Units::Centimeters.new(191)
|
43
|
+
|
44
|
+
Height.new(centimeters).centimeters.should == centimeters
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#to_s' do
|
49
|
+
it 'works without arguments' do
|
50
|
+
Height.new(191).to_s.should == '1m 91cm'
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'formats with metric system' do
|
54
|
+
Height.new(191).to_s(:default, :metric).should == '1m 91cm'
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'formats with imperial system' do
|
58
|
+
Height.new('6ft 3in').to_s(:default, :imperial).should == '6 ft 3 in'
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'raises when invalid system provided' do
|
62
|
+
expect { Height.new(191).to_s(:default, :alien) }.to raise_error(ArgumentError)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
data/spec/parser_spec.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Height::Parser do
|
4
|
+
describe '#centimeters' do
|
5
|
+
it { Height::Parser.new(191).centimeters.should == Height::Units::Centimeters.new(191) }
|
6
|
+
it { Height::Parser.new('191').centimeters.should == Height::Units::Centimeters.new(191) }
|
7
|
+
it { Height::Parser.new('1m 91cm').centimeters.should == Height::Units::Centimeters.new(191) }
|
8
|
+
it { Height::Parser.new('6 feet 3 inches').centimeters.should == Height::Units::Centimeters.new(191) }
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Height::Parsers::Imperial do
|
4
|
+
it { Height::Parsers::Imperial.new('6 feet 3 inches').inches.should == Height::Units::Inches.new(75) }
|
5
|
+
it { Height::Parsers::Imperial.new('6 feet').centimeters.should == Height::Units::Centimeters.new(183) }
|
6
|
+
it { Height::Parsers::Imperial.new('6 \'').meters.should == Height::Units::Meters.new(1.83) }
|
7
|
+
it { Height::Parsers::Imperial.new('6\' 3"').feet.should == Height::Units::Feet.new(6.25) }
|
8
|
+
it { Height::Parsers::Imperial.new('6ft 3in').feet.should == Height::Units::Feet.new(6.25) }
|
9
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Height::Parsers::Metric do
|
4
|
+
it { Height::Parsers::Metric.new(191).centimeters.should == Height::Units::Centimeters.new(191) }
|
5
|
+
it { Height::Parsers::Metric.new('191').centimeters.should == Height::Units::Centimeters.new(191) }
|
6
|
+
it { Height::Parsers::Metric.new('191 cm').centimeters.should == Height::Units::Centimeters.new(191) }
|
7
|
+
it { Height::Parsers::Metric.new('1m 91cm').inches.should == Height::Units::Inches.new(75) }
|
8
|
+
it { Height::Parsers::Metric.new('1m').meters.should == Height::Units::Meters.new(1) }
|
9
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'height'
|
2
|
+
require 'pry'
|
3
|
+
require 'i18n'
|
4
|
+
|
5
|
+
def reset_i18n
|
6
|
+
I18n.backend = I18n::Backend::Simple.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def units
|
10
|
+
[
|
11
|
+
Height::Units::Feet.new(6.25),
|
12
|
+
Height::Units::Inches.new(75),
|
13
|
+
Height::Units::Meters.new(1.91),
|
14
|
+
Height::Units::Centimeters.new(191)
|
15
|
+
]
|
16
|
+
end
|