much-decimal 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8327ce133aaff24d5e5e1a64b0a9b1ff0d36a6e8
4
- data.tar.gz: aa9bbbbcb110c82ef27f3568b8b2aa85e4c930e7
3
+ data.tar.gz: 617e4bc9765ffab1e22828a378f130a2b324324b
4
+ metadata.gz: d6a848633d4d805c2bb72fd67d05c21b2f4cf02e
5
5
  SHA512:
6
- metadata.gz: af8fc04ea539ed937a76d862a1ee3502e20ca11124ef8711761124d832de0612428cb34f2dbe59be0a79c719c5ffdaca79555f07dc664c1a10d44afdad031de0
7
- data.tar.gz: e4249e91a04087fa035c156c2f339b0a8a25eb418a22eba1434c7468a33632c2f406bd5dca1e3b312ff9bcfe348a940fa40cffe209da86243c6dd2a930653b8c
6
+ data.tar.gz: 4a824dfd66b88e3590ee928bf3e43c6032af340d67161376173e72faf26ce6c6aa906002b6a1180d2632449c16ae4c21af18e469c6bf8f9c862cdcac18a235a1
7
+ metadata.gz: 6502e2327e568bf68a1f4623fa0dc958f677df0288f5ed26f068a330cfb85ad47c3df25e680919fc78c3563cde68c240f3ad80ea5862d8f24149a8ce9f66f84b
data/lib/much-decimal.rb CHANGED
@@ -1,5 +1,77 @@
1
- require "much-decimal/version"
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
@@ -1,3 +1,3 @@
1
1
  module MuchDecimal
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/much-decimal.gemspec CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |gem|
19
19
  gem.require_paths = ["lib"]
20
20
 
21
21
  gem.add_development_dependency("assert", ["~> 2.16.1"])
22
- # TODO: gem.add_dependency("gem-name", ["~> 0.0.0"])
22
+
23
+ gem.add_dependency('much-plugin', ["~> 0.1.1"])
23
24
 
24
25
  end
@@ -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.1
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-06 00:00:00 Z
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
- - &id002
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
- - *id002
76
+ - *id003
66
77
  requirements: []
67
78
 
68
79
  rubyforge_project:
69
- rubygems_version: 2.6.4
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