percentage 1.0.0 → 1.4.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.
- checksums.yaml +7 -0
- data/CHANGES.md +35 -0
- data/LICENSE.txt +4 -0
- data/README.md +40 -19
- data/lib/percentage.rb +25 -8
- data/lib/percentage/yaml.rb +29 -0
- data/percentage.gemspec +12 -4
- metadata +23 -21
- data/Rakefile.rb +0 -7
- data/spec/percentage_spec.rb +0 -352
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 20e2362952bb7911cca151e3df92aa1fbd1673d165c745ca577aa7fa269c5d79
|
4
|
+
data.tar.gz: 82c0f31ba57b5e8eae7e4c9bf3e27cd202f32fa30d6f7ae544d519499e19cd37
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 575215d64aaf5a84851d29e732902abc07239bf0be3e8a542ce8e332272b9c2470cfc6bc4c7d1337d180f2a2249cb854b3fbdf6fc3b697ef0a5f126680bc423b
|
7
|
+
data.tar.gz: 1e7ca91c861e49039fd592a82f54c9778ba335efc6286b9ab772c4f634db536e58eb429d9a839e1013684f435aa77c942210d8fcadfb2d49cac73dfbf449ea04
|
data/CHANGES.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# 1.4.1
|
2
|
+
|
3
|
+
* Added CHANGES.md to gem files
|
4
|
+
|
5
|
+
* Fixed outdated changelog_uri
|
6
|
+
|
7
|
+
# 1.4.0
|
8
|
+
|
9
|
+
* Added optional YAML integration
|
10
|
+
|
11
|
+
This makes it possible to dump/load percentage objects to/from YAML as scalar values. For example:
|
12
|
+
|
13
|
+
require 'percentage/yaml'
|
14
|
+
|
15
|
+
puts YAML.dump([Percentage(BigDecimal('17.5'))])
|
16
|
+
|
17
|
+
This functionality is not enabled by default, due to the use of Module#prepend.
|
18
|
+
|
19
|
+
# 1.3.0
|
20
|
+
|
21
|
+
* Added ndigits argument to Percentage#truncate
|
22
|
+
|
23
|
+
# 1.2.0
|
24
|
+
|
25
|
+
* Removed memoization so that Percentage objects can be frozen (thanks @iamvery)
|
26
|
+
|
27
|
+
# 1.1.0
|
28
|
+
|
29
|
+
* Added BigDecimal#to_percentage and Integer#to_percentage
|
30
|
+
|
31
|
+
* Added BigDecimal#percent_of (thanks @mikeymicrophone)
|
32
|
+
|
33
|
+
# 1.0.0
|
34
|
+
|
35
|
+
* First version!
|
data/LICENSE.txt
ADDED
data/README.md
CHANGED
@@ -1,15 +1,27 @@
|
|
1
|
-
|
2
|
-
==========
|
1
|
+
# percentage
|
3
2
|
|
3
|
+

|
4
|
+

|
4
5
|
|
5
|
-
A little library for working with percentages.
|
6
6
|
|
7
|
+
Ruby gem for working with percentages.
|
7
8
|
|
8
|
-
Feature Tour
|
9
|
-
------------
|
10
9
|
|
11
|
-
|
12
|
-
|
10
|
+
## Install
|
11
|
+
|
12
|
+
Using Bundler:
|
13
|
+
|
14
|
+
$ bundle add percentage
|
15
|
+
|
16
|
+
Using RubyGems:
|
17
|
+
|
18
|
+
$ gem install percentage
|
19
|
+
|
20
|
+
|
21
|
+
## Constructing Percentages
|
22
|
+
|
23
|
+
The `Percentage` method converts numeric objects to percentage objects
|
24
|
+
with values that you would expect:
|
13
25
|
|
14
26
|
```ruby
|
15
27
|
Percentage(50) # => 50%
|
@@ -20,7 +32,7 @@ Percentage(Rational(25, 2)) # => 12.5%
|
|
20
32
|
```
|
21
33
|
|
22
34
|
Percentage objects can also be constructed directly, but in this case
|
23
|
-
BigDecimal/Rational values are treated as fractions
|
35
|
+
BigDecimal/Rational values are treated as fractions:
|
24
36
|
|
25
37
|
```ruby
|
26
38
|
Percentage.new(50) # => 50%
|
@@ -30,6 +42,19 @@ Percentage.new(BigDecimal('0.175')) # => 17.5%
|
|
30
42
|
Percentage.new(Rational(1, 8)) # => 12.5%
|
31
43
|
```
|
32
44
|
|
45
|
+
Some shortcut methods are defined on Integer and BigDecimal for convenience:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
50.percent # => 50%
|
49
|
+
|
50
|
+
5.as_percentage_of(10) # => 50.0%
|
51
|
+
|
52
|
+
BigDecimal('2.9').to_percentage # => 2.9%
|
53
|
+
```
|
54
|
+
|
55
|
+
|
56
|
+
## Numeric features
|
57
|
+
|
33
58
|
As with other numerics, percentage objects are conceptually immutable.
|
34
59
|
Common numeric functionality like `to_i`, `to_f`, `to_s`, `to_r`, `zero?`,
|
35
60
|
and equality/comparison methods are defined.
|
@@ -46,9 +71,9 @@ They can also be "scaled up" using the `scale` method:
|
|
46
71
|
Percentage(10).scale(5) # => 50%
|
47
72
|
```
|
48
73
|
|
49
|
-
Multiplication is
|
50
|
-
BigDecimal objects can't be coerced into rational objects, so the
|
51
|
-
|
74
|
+
Multiplication is defined using the fractional value of the percentage.
|
75
|
+
BigDecimal objects can't be coerced into rational objects, so the
|
76
|
+
multiplication order will matter in some cases, for example:
|
52
77
|
|
53
78
|
```ruby
|
54
79
|
Percentage(50) * 10 # => (5/1)
|
@@ -61,23 +86,19 @@ Percentage(50) * BigDecimal('150.00') # raises TypeError
|
|
61
86
|
```
|
62
87
|
|
63
88
|
|
64
|
-
Bonus
|
65
|
-
------------
|
89
|
+
## Bonus extras
|
66
90
|
|
67
|
-
|
91
|
+
There's a #percent_of method defined on Integer and BigDecimal for percentage calculations:
|
68
92
|
|
69
93
|
```ruby
|
70
|
-
50.percent # => 50%
|
71
|
-
|
72
94
|
50.percent_of(BigDecimal(150)) # => BigDecimal('75.00')
|
73
95
|
|
74
96
|
10.percent_of(100) # => (10/1)
|
75
97
|
|
76
|
-
5.
|
98
|
+
BigDecimal('0.5').percent_of(88) # => BigDecimal('0.44')
|
77
99
|
```
|
78
100
|
|
79
|
-
|
80
|
-
change between two values:
|
101
|
+
There's also a `Percentage.change` method for calculating the percentage change between two values:
|
81
102
|
|
82
103
|
```ruby
|
83
104
|
Percentage.change(2, 3) # => 50.0%
|
data/lib/percentage.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'rational'
|
2
1
|
require 'bigdecimal'
|
3
2
|
|
4
3
|
class Percentage
|
@@ -76,8 +75,16 @@ class Percentage
|
|
76
75
|
end
|
77
76
|
end
|
78
77
|
|
79
|
-
def truncate(
|
80
|
-
self.
|
78
|
+
def truncate(ndigits = nil)
|
79
|
+
return self if @value.integer?
|
80
|
+
|
81
|
+
value = @value * 100
|
82
|
+
|
83
|
+
if ndigits.nil?
|
84
|
+
self.class.new(value.truncate)
|
85
|
+
else
|
86
|
+
self.class.new(value.truncate(ndigits) / 100)
|
87
|
+
end
|
81
88
|
end
|
82
89
|
|
83
90
|
def scale(n)
|
@@ -87,7 +94,7 @@ class Percentage
|
|
87
94
|
protected
|
88
95
|
|
89
96
|
def fractional_value
|
90
|
-
@
|
97
|
+
@value.integer? ? Rational(@value, 100) : @value
|
91
98
|
end
|
92
99
|
|
93
100
|
private
|
@@ -98,7 +105,7 @@ class Percentage
|
|
98
105
|
elsif BigDecimal === @value
|
99
106
|
(@value * 100).to_s('F')
|
100
107
|
else
|
101
|
-
|
108
|
+
(@value * 100).to_f.to_s
|
102
109
|
end
|
103
110
|
end
|
104
111
|
end
|
@@ -112,18 +119,28 @@ def Percentage.change(a, b)
|
|
112
119
|
end
|
113
120
|
|
114
121
|
class BigDecimal
|
122
|
+
def to_percentage
|
123
|
+
Percentage(self)
|
124
|
+
end
|
125
|
+
|
126
|
+
def percent_of(n)
|
127
|
+
n * Percentage(self)
|
128
|
+
end
|
129
|
+
|
115
130
|
def as_percentage_of(n)
|
116
131
|
Percentage.new(self / n)
|
117
132
|
end
|
118
133
|
end
|
119
134
|
|
120
135
|
class Integer
|
121
|
-
def
|
122
|
-
Percentage
|
136
|
+
def to_percentage
|
137
|
+
Percentage(self)
|
123
138
|
end
|
124
139
|
|
140
|
+
alias_method :percent, :to_percentage
|
141
|
+
|
125
142
|
def percent_of(n)
|
126
|
-
n * Percentage
|
143
|
+
n * Percentage(self)
|
127
144
|
end
|
128
145
|
|
129
146
|
def as_percentage_of(n)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
class Percentage
|
4
|
+
def encode_with(coder)
|
5
|
+
coder.represent_scalar(nil, to_s)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ScalarScannerPatch
|
9
|
+
INTEGER = /\A(\d+)%\z/
|
10
|
+
|
11
|
+
DECIMAL = /\A(\d+\.\d+)%\z/
|
12
|
+
|
13
|
+
def tokenize(string)
|
14
|
+
if !string.empty? && string.match(INTEGER)
|
15
|
+
return Percentage($1.to_i)
|
16
|
+
end
|
17
|
+
|
18
|
+
if !string.empty? && string.match(DECIMAL)
|
19
|
+
return Percentage(BigDecimal($1))
|
20
|
+
end
|
21
|
+
|
22
|
+
super string
|
23
|
+
end
|
24
|
+
|
25
|
+
YAML::ScalarScanner.prepend(self)
|
26
|
+
end
|
27
|
+
|
28
|
+
private_constant :ScalarScannerPatch
|
29
|
+
end
|
data/percentage.gemspec
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'percentage'
|
3
|
-
s.version = '1.
|
3
|
+
s.version = '1.4.1'
|
4
|
+
s.license = 'LGPL-3.0'
|
4
5
|
s.platform = Gem::Platform::RUBY
|
5
6
|
s.authors = ['Tim Craft']
|
6
7
|
s.email = ['mail@timcraft.com']
|
7
|
-
s.homepage = '
|
8
|
-
s.description = '
|
8
|
+
s.homepage = 'https://github.com/readysteady/percentage'
|
9
|
+
s.description = 'Ruby gem for working with percentages'
|
9
10
|
s.summary = 'See description'
|
10
|
-
s.files = Dir.glob('
|
11
|
+
s.files = Dir.glob('lib/**/*.rb') + %w[CHANGES.md LICENSE.txt README.md percentage.gemspec]
|
12
|
+
s.required_ruby_version = '>= 1.9.3'
|
11
13
|
s.require_path = 'lib'
|
14
|
+
s.metadata = {
|
15
|
+
'homepage' => 'https://github.com/readysteady/percentage',
|
16
|
+
'source_code_uri' => 'https://github.com/readysteady/percentage',
|
17
|
+
'bug_tracker_uri' => 'https://github.com/readysteady/percentage/issues',
|
18
|
+
'changelog_uri' => 'https://github.com/readysteady/percentage/blob/main/CHANGES.md'
|
19
|
+
}
|
12
20
|
end
|
metadata
CHANGED
@@ -1,51 +1,53 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: percentage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.4.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Tim Craft
|
9
|
-
autorequire:
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2020-11-03 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
|
-
description:
|
13
|
+
description: Ruby gem for working with percentages
|
15
14
|
email:
|
16
15
|
- mail@timcraft.com
|
17
16
|
executables: []
|
18
17
|
extensions: []
|
19
18
|
extra_rdoc_files: []
|
20
19
|
files:
|
21
|
-
-
|
22
|
-
-
|
20
|
+
- CHANGES.md
|
21
|
+
- LICENSE.txt
|
23
22
|
- README.md
|
24
|
-
-
|
23
|
+
- lib/percentage.rb
|
24
|
+
- lib/percentage/yaml.rb
|
25
25
|
- percentage.gemspec
|
26
|
-
homepage:
|
27
|
-
licenses:
|
28
|
-
|
26
|
+
homepage: https://github.com/readysteady/percentage
|
27
|
+
licenses:
|
28
|
+
- LGPL-3.0
|
29
|
+
metadata:
|
30
|
+
homepage: https://github.com/readysteady/percentage
|
31
|
+
source_code_uri: https://github.com/readysteady/percentage
|
32
|
+
bug_tracker_uri: https://github.com/readysteady/percentage/issues
|
33
|
+
changelog_uri: https://github.com/readysteady/percentage/blob/main/CHANGES.md
|
34
|
+
post_install_message:
|
29
35
|
rdoc_options: []
|
30
36
|
require_paths:
|
31
37
|
- lib
|
32
38
|
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
39
|
requirements:
|
35
|
-
- -
|
40
|
+
- - ">="
|
36
41
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
42
|
+
version: 1.9.3
|
38
43
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
44
|
requirements:
|
41
|
-
- -
|
45
|
+
- - ">="
|
42
46
|
- !ruby/object:Gem::Version
|
43
47
|
version: '0'
|
44
48
|
requirements: []
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
specification_version: 3
|
49
|
+
rubygems_version: 3.1.4
|
50
|
+
signing_key:
|
51
|
+
specification_version: 4
|
49
52
|
summary: See description
|
50
53
|
test_files: []
|
51
|
-
has_rdoc:
|
data/Rakefile.rb
DELETED
data/spec/percentage_spec.rb
DELETED
@@ -1,352 +0,0 @@
|
|
1
|
-
require 'minitest/autorun'
|
2
|
-
|
3
|
-
require_relative '../lib/percentage'
|
4
|
-
|
5
|
-
describe 'Percentage object' do
|
6
|
-
it 'is comparable' do
|
7
|
-
percentage = Percentage.new(Rational(1, 8))
|
8
|
-
|
9
|
-
(Comparable === percentage).must_equal(true)
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'is comparable to other objects of the same class' do
|
13
|
-
(Percentage.new(Rational(1, 8)) > Percentage.new(Rational(1, 10))).must_equal(true)
|
14
|
-
end
|
15
|
-
|
16
|
-
it 'is comparable to other numeric objects' do
|
17
|
-
(Percentage.new(Rational(1, 8)) > Rational(1, 10)).must_equal(true)
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'can be used as a hash key' do
|
21
|
-
hash = Hash.new(0)
|
22
|
-
|
23
|
-
3.times { hash[Percentage.new(Rational(1, 10))] += 1 }
|
24
|
-
|
25
|
-
hash[Percentage.new(Rational(1, 10))].must_equal(3)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe 'Percentage object initialized with an integer value' do
|
30
|
-
before do
|
31
|
-
@percentage = Percentage.new(10)
|
32
|
-
end
|
33
|
-
|
34
|
-
describe 'value method' do
|
35
|
-
it 'returns the value passed to the constructor' do
|
36
|
-
@percentage.value.must_equal(10)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe 'to_i method' do
|
41
|
-
it 'returns the integer value of the percentage' do
|
42
|
-
@percentage.to_i.must_equal(10)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
describe 'to_f method' do
|
47
|
-
it 'returns the float value of the percentage' do
|
48
|
-
@percentage.to_f.must_be_close_to(10.0)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe 'to_s method' do
|
53
|
-
it 'returns the integer value of the percentage suffixed with the percent symbol' do
|
54
|
-
@percentage.to_s.must_equal('10%')
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe 'to_r method' do
|
59
|
-
it 'returns the rational value of the percentage' do
|
60
|
-
@percentage.to_r.must_equal(Rational(1, 10))
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
describe 'zero query method' do
|
65
|
-
it 'returns true if the percentage has a zero value' do
|
66
|
-
Percentage.new(0).zero?.must_equal(true)
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'returns false otherwise' do
|
70
|
-
@percentage.zero?.must_equal(false)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
describe 'truncate method' do
|
75
|
-
it 'returns a percentage object with a truncated rational value' do
|
76
|
-
percentage = @percentage.truncate(1)
|
77
|
-
percentage.must_be_instance_of(Percentage)
|
78
|
-
percentage.value.must_equal(Rational(1, 10))
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
describe 'scale method' do
|
83
|
-
it 'returns a percentage object with the value of the percentage multiplied by the integer argument' do
|
84
|
-
percentage = @percentage.scale(2)
|
85
|
-
percentage.must_be_instance_of(Percentage)
|
86
|
-
percentage.value.must_equal(20)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
describe 'Percentage object initialized with a rational value' do
|
92
|
-
before do
|
93
|
-
@percentage = Percentage.new(Rational(1, 8))
|
94
|
-
end
|
95
|
-
|
96
|
-
describe 'value method' do
|
97
|
-
it 'returns the value passed to the constructor' do
|
98
|
-
@percentage.value.must_equal(Rational(1, 8))
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
describe 'to_i method' do
|
103
|
-
it 'returns the integer value of the percentage' do
|
104
|
-
@percentage.to_i.must_equal(12)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
describe 'to_f method' do
|
109
|
-
it 'returns the float value of the percentage' do
|
110
|
-
@percentage.to_f.must_be_close_to(12.5)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
describe 'to_s method' do
|
115
|
-
it 'returns the decimal value of the percentage suffixed with the percent symbol' do
|
116
|
-
@percentage.to_s.must_equal('12.5%')
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
describe 'to_r method' do
|
121
|
-
it 'returns the rational value of the percentage' do
|
122
|
-
@percentage.to_r.must_equal(Rational(1, 8))
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
describe 'zero query method' do
|
127
|
-
it 'returns true if the percentage has a zero value' do
|
128
|
-
Percentage.new(Rational(0)).zero?.must_equal(true)
|
129
|
-
end
|
130
|
-
|
131
|
-
it 'returns false otherwise' do
|
132
|
-
@percentage.zero?.must_equal(false)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
describe 'truncate method' do
|
137
|
-
it 'returns a percentage object with a truncated rational value' do
|
138
|
-
percentage = @percentage.truncate(1)
|
139
|
-
percentage.must_be_instance_of(Percentage)
|
140
|
-
percentage.value.must_equal(Rational(1, 10))
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
describe 'scale method' do
|
145
|
-
it 'returns a percentage object with the value of the percentage multiplied by the integer argument' do
|
146
|
-
percentage = @percentage.scale(2)
|
147
|
-
percentage.must_be_instance_of(Percentage)
|
148
|
-
percentage.value.must_equal(Rational(1, 4))
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
describe 'Percentage object initialized with a decimal value' do
|
154
|
-
before do
|
155
|
-
@percentage = Percentage.new(BigDecimal('0.175'))
|
156
|
-
end
|
157
|
-
|
158
|
-
describe 'value method' do
|
159
|
-
it 'returns the value passed to the constructor' do
|
160
|
-
@percentage.value.must_equal(BigDecimal('0.175'))
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
describe 'to_i method' do
|
165
|
-
it 'returns the integer value of the percentage' do
|
166
|
-
@percentage.to_i.must_equal(17)
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
describe 'to_f method' do
|
171
|
-
it 'returns the float value of the percentage' do
|
172
|
-
@percentage.to_f.must_be_close_to(17.5)
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
describe 'to_s method' do
|
177
|
-
it 'returns the decimal value of the percentage suffixed with the percent symbol' do
|
178
|
-
@percentage.to_s.must_equal('17.5%')
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
describe 'to_r method' do
|
183
|
-
it 'returns the rational value of the percentage' do
|
184
|
-
@percentage.to_r.must_equal(Rational(175, 1000))
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
describe 'zero query method' do
|
189
|
-
it 'returns true if the percentage has a zero value' do
|
190
|
-
Percentage.new(BigDecimal(0)).zero?.must_equal(true)
|
191
|
-
end
|
192
|
-
|
193
|
-
it 'returns false otherwise' do
|
194
|
-
@percentage.zero?.must_equal(false)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
describe 'truncate method' do
|
199
|
-
it 'returns a percentage object with a truncated decimal value' do
|
200
|
-
percentage = @percentage.truncate(1)
|
201
|
-
percentage.must_be_instance_of(Percentage)
|
202
|
-
percentage.value.must_equal(BigDecimal('0.1'))
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
describe 'scale method' do
|
207
|
-
it 'returns a percentage object with the value of the percentage multiplied by the integer argument' do
|
208
|
-
percentage = @percentage.scale(2)
|
209
|
-
percentage.must_be_instance_of(Percentage)
|
210
|
-
percentage.value.must_equal(BigDecimal('0.35'))
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
describe 'Addition of percentage objects' do
|
216
|
-
it 'returns a percentage object with the value of the two percentages added together' do
|
217
|
-
percentage = Percentage.new(10) + Percentage.new(10)
|
218
|
-
percentage.must_be_instance_of(Percentage)
|
219
|
-
percentage.value.must_equal(20)
|
220
|
-
|
221
|
-
percentage = Percentage.new(Rational(1, 8)) + Percentage.new(10)
|
222
|
-
percentage.must_be_instance_of(Percentage)
|
223
|
-
percentage.value.must_equal(Rational(9, 40))
|
224
|
-
|
225
|
-
percentage = Percentage.new(BigDecimal('0.175')) + Percentage.new(BigDecimal('0.025'))
|
226
|
-
percentage.must_be_instance_of(Percentage)
|
227
|
-
percentage.value.must_equal(BigDecimal('0.2'))
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
describe 'Addition of percentage object with another type of object' do
|
232
|
-
it 'raises an exception' do
|
233
|
-
proc { Percentage.new(10) + 5 }.must_raise(TypeError)
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
describe 'Multiplication of percentage objects' do
|
238
|
-
it 'returns a percentage object with the fractional value of the two percentages multiplied together' do
|
239
|
-
percentage = Percentage.new(10) * Percentage.new(10)
|
240
|
-
percentage.must_be_instance_of(Percentage)
|
241
|
-
percentage.value.must_equal(Rational(1, 100))
|
242
|
-
|
243
|
-
percentage = Percentage.new(Rational(1, 8)) * Percentage.new(10)
|
244
|
-
percentage.must_be_instance_of(Percentage)
|
245
|
-
percentage.value.must_equal(Rational(1, 80))
|
246
|
-
|
247
|
-
percentage = Percentage.new(BigDecimal('0.175')) * Percentage.new(10)
|
248
|
-
percentage.must_be_instance_of(Percentage)
|
249
|
-
percentage.value.must_equal(Rational(7, 400))
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
describe 'Multiplication of a decimal object with a percentage object' do
|
254
|
-
it 'returns a decimal object with the value of the decimal multiplied by the fractional value of the percentage' do
|
255
|
-
percentage, decimal = Percentage.new(BigDecimal('0.175')), BigDecimal('99.00')
|
256
|
-
|
257
|
-
(decimal * percentage).must_equal(BigDecimal('17.325'))
|
258
|
-
(percentage * decimal).must_equal(BigDecimal('17.325'))
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
describe 'Percentage object equality' do
|
263
|
-
describe 'double equals method' do
|
264
|
-
it 'returns true for percentage objects with the same fractional value' do
|
265
|
-
(Percentage.new(50) == Percentage.new(50)).must_equal(true)
|
266
|
-
(Percentage.new(50) == Percentage.new(Rational(1, 2))).must_equal(true)
|
267
|
-
(Percentage.new(50) == Percentage.new(BigDecimal('0.5'))).must_equal(true)
|
268
|
-
end
|
269
|
-
|
270
|
-
it 'returns false otherwise' do
|
271
|
-
(Percentage.new(50) == Percentage.new(100)).must_equal(false)
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
describe 'eql query method' do
|
276
|
-
it 'returns true for percentage objects with exactly the same fractional value' do
|
277
|
-
(Percentage.new(50).eql? Percentage.new(50)).must_equal(true)
|
278
|
-
end
|
279
|
-
|
280
|
-
it 'returns false otherwise' do
|
281
|
-
(Percentage.new(50).eql? Percentage.new(Rational(1, 2))).must_equal(false)
|
282
|
-
(Percentage.new(50).eql? Percentage.new(BigDecimal('0.5'))).must_equal(false)
|
283
|
-
(Percentage.new(50).eql? Percentage.new(100)).must_equal(false)
|
284
|
-
end
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
describe 'Percentage method' do
|
289
|
-
describe 'when called with an integer argument' do
|
290
|
-
it 'returns a percentage object with the integer value' do
|
291
|
-
percentage = Percentage(10)
|
292
|
-
percentage.must_be_instance_of(Percentage)
|
293
|
-
percentage.value.must_equal(10)
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
describe 'when called with a decimal argument' do
|
298
|
-
it 'returns a percentage object with the value of the argument divided by 100' do
|
299
|
-
percentage = Percentage(BigDecimal('17.5'))
|
300
|
-
percentage.must_be_instance_of(Percentage)
|
301
|
-
percentage.value.must_equal(BigDecimal('0.175'))
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
|
-
describe 'when called with a rational argument' do
|
306
|
-
it 'returns a percentage object with the value of the argument divided by 100' do
|
307
|
-
percentage = Percentage(Rational(100, 3))
|
308
|
-
percentage.must_be_instance_of(Percentage)
|
309
|
-
percentage.value.must_equal(Rational(1, 3))
|
310
|
-
end
|
311
|
-
end
|
312
|
-
end
|
313
|
-
|
314
|
-
describe 'Percentage change method' do
|
315
|
-
it 'returns the difference between the arguments as a percentage of the first argument' do
|
316
|
-
percentage = Percentage.change(2, 3)
|
317
|
-
percentage.must_be_instance_of(Percentage)
|
318
|
-
percentage.must_equal(Percentage.new(50))
|
319
|
-
end
|
320
|
-
end
|
321
|
-
|
322
|
-
describe 'BigDecimal as_percentage_of method' do
|
323
|
-
it 'returns a percentage object with the value of the decimal divided by the argument' do
|
324
|
-
percentage = BigDecimal('50.00').as_percentage_of(BigDecimal('100.00'))
|
325
|
-
percentage.must_be_instance_of(Percentage)
|
326
|
-
percentage.value.must_equal(BigDecimal('0.5'))
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
describe 'Integer percent method' do
|
331
|
-
it 'returns a percentage object with the value of the integer' do
|
332
|
-
percentage = 10.percent
|
333
|
-
percentage.must_be_instance_of(Percentage)
|
334
|
-
percentage.value.must_equal(10)
|
335
|
-
end
|
336
|
-
end
|
337
|
-
|
338
|
-
describe 'Integer percent_of method' do
|
339
|
-
it 'returns the value of the receiver as a percentage multiplied by the argument' do
|
340
|
-
10.percent_of(100).must_equal(10)
|
341
|
-
10.percent_of(BigDecimal(15)).must_equal(BigDecimal('1.5'))
|
342
|
-
10.percent_of(Rational(150, 2)).must_equal(Rational(15, 2))
|
343
|
-
end
|
344
|
-
end
|
345
|
-
|
346
|
-
describe 'Integer as_percentage_of method' do
|
347
|
-
it 'returns a percentage object with the value of the integer divided by the argument' do
|
348
|
-
percentage = 10.as_percentage_of(20)
|
349
|
-
percentage.must_be_instance_of(Percentage)
|
350
|
-
percentage.value.must_equal(Rational(1, 2))
|
351
|
-
end
|
352
|
-
end
|