much-decimal 0.0.1 → 0.1.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.
- checksums.yaml +4 -4
- data/lib/much-decimal.rb +73 -1
- data/lib/much-decimal/version.rb +1 -1
- data/much-decimal.gemspec +2 -1
- data/test/unit/much_decimal_tests.rb +220 -0
- metadata +17 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
|
4
|
-
|
3
|
+
data.tar.gz: 617e4bc9765ffab1e22828a378f130a2b324324b
|
4
|
+
metadata.gz: d6a848633d4d805c2bb72fd67d05c21b2f4cf02e
|
5
5
|
SHA512:
|
6
|
-
|
7
|
-
|
6
|
+
data.tar.gz: 4a824dfd66b88e3590ee928bf3e43c6032af340d67161376173e72faf26ce6c6aa906002b6a1180d2632449c16ae4c21af18e469c6bf8f9c862cdcac18a235a1
|
7
|
+
metadata.gz: 6502e2327e568bf68a1f4623fa0dc958f677df0288f5ed26f068a330cfb85ad47c3df25e680919fc78c3563cde68c240f3ad80ea5862d8f24149a8ce9f66f84b
|
data/lib/much-decimal.rb
CHANGED
@@ -1,5 +1,77 @@
|
|
1
|
-
require
|
1
|
+
require 'much-plugin'
|
2
|
+
|
3
|
+
require 'much-decimal/version'
|
2
4
|
|
3
5
|
module MuchDecimal
|
6
|
+
include MuchPlugin
|
7
|
+
|
8
|
+
DEFAULT_PRECISION = 2.freeze
|
9
|
+
|
10
|
+
def self.integer_to_decimal(integer, precision)
|
11
|
+
if integer.respond_to?(:to_i) && !integer.to_s.empty?
|
12
|
+
base_10_modifier = (10.0 ** precision)
|
13
|
+
integer.to_i / base_10_modifier
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.decimal_to_integer(decimal, precision)
|
18
|
+
if decimal.respond_to?(:to_f) && !decimal.to_s.empty?
|
19
|
+
base_10_modifier = (10.0 ** precision)
|
20
|
+
(decimal.to_f * base_10_modifier).round.to_i
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
plugin_included do
|
25
|
+
extend ClassMethods
|
26
|
+
end
|
27
|
+
|
28
|
+
module ClassMethods
|
29
|
+
|
30
|
+
def decimal_as_integer(attribute, options = nil)
|
31
|
+
options ||= {}
|
32
|
+
source = options[:source] || "#{attribute}_as_integer"
|
33
|
+
precision = (options[:precision] || DEFAULT_PRECISION).to_i
|
34
|
+
|
35
|
+
define_method(attribute) do
|
36
|
+
integer = self.send(source)
|
37
|
+
MuchDecimal.integer_to_decimal(integer, precision)
|
38
|
+
end
|
39
|
+
|
40
|
+
define_method("#{attribute}=") do |decimal|
|
41
|
+
integer = MuchDecimal.decimal_to_integer(decimal, precision)
|
42
|
+
self.send("#{source}=", integer)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
module TestHelpers
|
49
|
+
include MuchPlugin
|
50
|
+
|
51
|
+
plugin_included do
|
52
|
+
include InstanceMethods
|
53
|
+
|
54
|
+
require 'assert/factory'
|
55
|
+
end
|
56
|
+
|
57
|
+
module InstanceMethods
|
58
|
+
|
59
|
+
def assert_decimal_as_integer(subject, attribute, options = nil)
|
60
|
+
options ||= {}
|
61
|
+
source = options[:source] || "#{attribute}_as_integer"
|
62
|
+
precision = (options[:precision] || DEFAULT_PRECISION).to_i
|
63
|
+
|
64
|
+
value = Assert::Factory.float
|
65
|
+
subject.send("#{attribute}=", value)
|
66
|
+
|
67
|
+
exp = MuchDecimal.decimal_to_integer(value, precision)
|
68
|
+
assert_equal exp, subject.send(source)
|
69
|
+
exp = MuchDecimal.integer_to_decimal(exp, precision)
|
70
|
+
assert_equal exp, subject.send(attribute)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
4
76
|
|
5
77
|
end
|
data/lib/much-decimal/version.rb
CHANGED
data/much-decimal.gemspec
CHANGED
@@ -0,0 +1,220 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'much-decimal'
|
3
|
+
|
4
|
+
module MuchDecimal
|
5
|
+
|
6
|
+
class UnitTests < Assert::Context
|
7
|
+
desc "MuchDecimal"
|
8
|
+
setup do
|
9
|
+
@module = MuchDecimal
|
10
|
+
end
|
11
|
+
subject{ @module }
|
12
|
+
|
13
|
+
should have_imeths :integer_to_decimal, :decimal_to_integer
|
14
|
+
|
15
|
+
should "use much-plugin" do
|
16
|
+
assert_includes MuchPlugin, subject
|
17
|
+
end
|
18
|
+
|
19
|
+
should "know its default precision" do
|
20
|
+
assert_equal 2, DEFAULT_PRECISION
|
21
|
+
end
|
22
|
+
|
23
|
+
should "know how to convert an integer to a decimal" do
|
24
|
+
integer = Factory.integer
|
25
|
+
precision = Factory.integer(10)
|
26
|
+
base_10_modifier = (10.0 ** precision)
|
27
|
+
|
28
|
+
exp = integer / base_10_modifier
|
29
|
+
assert_equal exp, subject.integer_to_decimal(integer, precision)
|
30
|
+
assert_equal exp, subject.integer_to_decimal(integer.to_s, precision)
|
31
|
+
|
32
|
+
invalid_value = [nil, '', true, false].sample
|
33
|
+
assert_nil subject.integer_to_decimal(invalid_value, precision)
|
34
|
+
end
|
35
|
+
|
36
|
+
should "know how to convert a decimal to an integer" do
|
37
|
+
decimal = Factory.float
|
38
|
+
precision = Factory.integer(10)
|
39
|
+
base_10_modifier = (10.0 ** precision)
|
40
|
+
|
41
|
+
exp = (decimal * base_10_modifier).round.to_i
|
42
|
+
assert_equal exp, subject.decimal_to_integer(decimal, precision)
|
43
|
+
assert_equal exp, subject.decimal_to_integer(decimal.to_s, precision)
|
44
|
+
|
45
|
+
invalid_value = [nil, '', true, false].sample
|
46
|
+
assert_nil subject.decimal_to_integer(invalid_value, precision)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class MixinSetupTests < UnitTests
|
52
|
+
setup do
|
53
|
+
@class = Class.new do
|
54
|
+
include MuchDecimal
|
55
|
+
attr_accessor :seconds_as_integer, :integer_seconds
|
56
|
+
end
|
57
|
+
end
|
58
|
+
subject{ @class }
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
class MixinTests < MixinSetupTests
|
63
|
+
desc "when mixed in"
|
64
|
+
|
65
|
+
should have_imeths :decimal_as_integer
|
66
|
+
|
67
|
+
should "add a decimal-as-integer accessor using `decimal_as_integer`" do
|
68
|
+
subject.decimal_as_integer :seconds
|
69
|
+
|
70
|
+
instance = subject.new
|
71
|
+
assert_respond_to :seconds, instance
|
72
|
+
assert_respond_to :seconds=, instance
|
73
|
+
|
74
|
+
decimal = Factory.float
|
75
|
+
integer = Factory.integer
|
76
|
+
|
77
|
+
instance.seconds = decimal
|
78
|
+
exp = @module.decimal_to_integer(decimal, DEFAULT_PRECISION)
|
79
|
+
assert_equal exp, instance.seconds_as_integer
|
80
|
+
|
81
|
+
instance.seconds_as_integer = integer
|
82
|
+
exp = @module.integer_to_decimal(integer, DEFAULT_PRECISION)
|
83
|
+
assert_equal exp, instance.seconds
|
84
|
+
end
|
85
|
+
|
86
|
+
should "allow specifying custom options using `decimal_as_integer`" do
|
87
|
+
source = :integer_seconds
|
88
|
+
precision = Factory.integer(5)
|
89
|
+
subject.decimal_as_integer :seconds, {
|
90
|
+
:source => source,
|
91
|
+
:precision => precision
|
92
|
+
}
|
93
|
+
|
94
|
+
instance = subject.new
|
95
|
+
assert_respond_to :seconds, instance
|
96
|
+
assert_respond_to :seconds=, instance
|
97
|
+
|
98
|
+
decimal = Factory.float
|
99
|
+
integer = Factory.integer
|
100
|
+
|
101
|
+
instance.seconds = decimal
|
102
|
+
exp = @module.decimal_to_integer(decimal, precision)
|
103
|
+
assert_equal exp, instance.send(source)
|
104
|
+
|
105
|
+
instance.send("#{source}=", integer)
|
106
|
+
exp = @module.integer_to_decimal(integer, precision)
|
107
|
+
assert_equal exp, instance.seconds
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
class EdgeCaseTests < UnitTests
|
113
|
+
desc "edge cases"
|
114
|
+
setup do
|
115
|
+
@class = Class.new do
|
116
|
+
include MuchDecimal
|
117
|
+
|
118
|
+
attr_accessor :ten_thousandth_seconds
|
119
|
+
|
120
|
+
decimal_as_integer(:seconds, {
|
121
|
+
:source => :ten_thousandth_seconds,
|
122
|
+
:precision => 4
|
123
|
+
})
|
124
|
+
end
|
125
|
+
@instance = @class.new
|
126
|
+
end
|
127
|
+
subject{ @instance }
|
128
|
+
|
129
|
+
should "allow writing and reading `nil` values" do
|
130
|
+
assert_nil subject.ten_thousandth_seconds
|
131
|
+
assert_nil subject.seconds
|
132
|
+
|
133
|
+
subject.seconds = 1.2345
|
134
|
+
assert_equal 12345, subject.ten_thousandth_seconds
|
135
|
+
assert_equal 1.2345, subject.seconds
|
136
|
+
|
137
|
+
assert_nothing_raised{ subject.seconds = nil }
|
138
|
+
assert_nil subject.seconds
|
139
|
+
assert_nil subject.ten_thousandth_seconds
|
140
|
+
end
|
141
|
+
|
142
|
+
should "write empty string values as `nil` values" do
|
143
|
+
subject.seconds = 1.2345
|
144
|
+
assert_not_nil subject.ten_thousandth_seconds
|
145
|
+
assert_not_nil subject.seconds
|
146
|
+
|
147
|
+
assert_nothing_raised{ subject.seconds = '' }
|
148
|
+
assert_nil subject.seconds
|
149
|
+
assert_nil subject.ten_thousandth_seconds
|
150
|
+
end
|
151
|
+
|
152
|
+
should "write values that can't be converted as `nil` values" do
|
153
|
+
subject.seconds = 1.2345
|
154
|
+
assert_not_nil subject.ten_thousandth_seconds
|
155
|
+
assert_not_nil subject.seconds
|
156
|
+
|
157
|
+
assert_nothing_raised{ subject.seconds = true }
|
158
|
+
assert_nil subject.seconds
|
159
|
+
assert_nil subject.ten_thousandth_seconds
|
160
|
+
end
|
161
|
+
|
162
|
+
should "handle decimals with less significant digits" do
|
163
|
+
subject.seconds = 1.12
|
164
|
+
assert_equal 11200, subject.ten_thousandth_seconds
|
165
|
+
assert_equal 1.12, subject.seconds
|
166
|
+
end
|
167
|
+
|
168
|
+
should "handle integers" do
|
169
|
+
subject.seconds = 5
|
170
|
+
assert_equal 50000, subject.ten_thousandth_seconds
|
171
|
+
assert_equal 5.0, subject.seconds
|
172
|
+
end
|
173
|
+
|
174
|
+
should "handle decimals that are less than 1" do
|
175
|
+
subject.seconds = 0.0001
|
176
|
+
assert_equal 1, subject.ten_thousandth_seconds
|
177
|
+
assert_equal 0.0001, subject.seconds
|
178
|
+
end
|
179
|
+
|
180
|
+
should "handle decimals with too many significant digits by rounding" do
|
181
|
+
subject.seconds = 1.00005
|
182
|
+
assert_equal 10001, subject.ten_thousandth_seconds
|
183
|
+
assert_equal 1.0001, subject.seconds
|
184
|
+
end
|
185
|
+
|
186
|
+
should "handle repeating decimals" do
|
187
|
+
subject.seconds = 1 / 3.0
|
188
|
+
assert_equal 3333, subject.ten_thousandth_seconds
|
189
|
+
assert_equal 0.3333, subject.seconds
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
class TestHelpersTests < MixinSetupTests
|
195
|
+
include MuchDecimal::TestHelpers
|
196
|
+
|
197
|
+
desc "TestHelpers"
|
198
|
+
setup do
|
199
|
+
@class.decimal_as_integer :seconds
|
200
|
+
@custom_precision = Factory.integer(10)
|
201
|
+
@class.decimal_as_integer :other_seconds, {
|
202
|
+
:source => :integer_seconds,
|
203
|
+
:precision => @custom_precision
|
204
|
+
}
|
205
|
+
|
206
|
+
@instance = @class.new
|
207
|
+
end
|
208
|
+
subject{ @instance }
|
209
|
+
|
210
|
+
should "provide helpers for testing that a class has json fields" do
|
211
|
+
assert_decimal_as_integer subject, :seconds
|
212
|
+
assert_decimal_as_integer subject, :other_seconds, {
|
213
|
+
:source => :integer_seconds,
|
214
|
+
:precision => @custom_precision
|
215
|
+
}
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: much-decimal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kelly Redding
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2016-06-
|
13
|
+
date: 2016-06-13 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: assert
|
@@ -22,6 +22,16 @@ dependencies:
|
|
22
22
|
version: 2.16.1
|
23
23
|
type: :development
|
24
24
|
version_requirements: *id001
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: much-plugin
|
27
|
+
prerelease: false
|
28
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.1.1
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id002
|
25
35
|
description: Define decimal attributes that are stored as integers
|
26
36
|
email:
|
27
37
|
- kelly@kellyredding.com
|
@@ -43,6 +53,7 @@ files:
|
|
43
53
|
- much-decimal.gemspec
|
44
54
|
- test/helper.rb
|
45
55
|
- test/support/factory.rb
|
56
|
+
- test/unit/much_decimal_tests.rb
|
46
57
|
- tmp/.gitkeep
|
47
58
|
homepage: https://github.com/redding/much-decimal
|
48
59
|
licenses:
|
@@ -56,20 +67,21 @@ require_paths:
|
|
56
67
|
- lib
|
57
68
|
required_ruby_version: !ruby/object:Gem::Requirement
|
58
69
|
requirements:
|
59
|
-
- &
|
70
|
+
- &id003
|
60
71
|
- ">="
|
61
72
|
- !ruby/object:Gem::Version
|
62
73
|
version: "0"
|
63
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
75
|
requirements:
|
65
|
-
- *
|
76
|
+
- *id003
|
66
77
|
requirements: []
|
67
78
|
|
68
79
|
rubyforge_project:
|
69
|
-
rubygems_version: 2.
|
80
|
+
rubygems_version: 2.5.1
|
70
81
|
signing_key:
|
71
82
|
specification_version: 4
|
72
83
|
summary: Define decimal attributes that are stored as integers
|
73
84
|
test_files:
|
74
85
|
- test/helper.rb
|
75
86
|
- test/support/factory.rb
|
87
|
+
- test/unit/much_decimal_tests.rb
|