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