percentable 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: a86a351aaeedff408bbab5f914b294f8a898f4a0
4
- data.tar.gz: 99d9e1bb82f6ff9e5f9242518240d113f5c9f31f
3
+ metadata.gz: 0fbd045effde2a7949bd1f83593a92c8d320abf1
4
+ data.tar.gz: 0f629c3a9f5afb113e17a62265d47320cb78ae4d
5
5
  SHA512:
6
- metadata.gz: 304b7c8663f0b5a6764d0e9b6739765d054c1a768a9247b20fa65d1e108e66405e9338f26f74213ac2eb39c03d42e4a7664f9d700cb60eca6175ee2833f9356d
7
- data.tar.gz: b8323fc3c48aa7b7a1e448bea8694bbc23b3bea7a9c2fb206e4b52121b6aad1b2bba554a9c441dfc93291b10512f908ecad1649447e433d9eb28765d3c47ab8e
6
+ metadata.gz: 21674843db344a6ae56bab761521e302194d7350c891ccc0ee15d567f36ab1902e4590fb6c86878d12130550aaade1f602f9c0883ca35fe66160c7a610bd56eb
7
+ data.tar.gz: a9709db91180a7edb2498cbaee2a23d4999fdb0087d905ce9f236f2e1b6d6708f9765892ec8953f5b712d1013ea1add97a37be9afe9a9b48c4064542eb8de287
data/README.md CHANGED
@@ -1,3 +1,8 @@
1
+ [![Gem Version](https://badge.fury.io/rb/percentable.png)](http://badge.fury.io/rb/percentable)
2
+ [![Build Status](https://travis-ci.org/ericroberts/percentable.png?branch=master)](https://travis-ci.org/ericroberts/percentable)
3
+ [![Code Climate](https://codeclimate.com/github/ericroberts/percentable.png)](https://codeclimate.com/github/ericroberts/percentable)
4
+ [![Coverage Status](https://coveralls.io/repos/ericroberts/percentable/badge.png?branch=master)](https://coveralls.io/r/ericroberts/percentable?branch=master)
5
+
1
6
  # Percentable
2
7
 
3
8
  Small gem to make working with percents easier.
@@ -37,7 +42,7 @@ That's the basics of the object itself. You probably want to know about how it w
37
42
  percent = Percent.new(10)
38
43
  percent + percent #=> Percent.new(20)
39
44
  percent - percent #=> Percent.new(0)
40
- percent * percent #=> Percent.new(100)
45
+ percent * percent #=> Percent.new(1)
41
46
  percent / percent #=> Percent.new(1)
42
47
  ```
43
48
 
@@ -51,6 +56,16 @@ percent * 10 #=> Percent.new(500)
51
56
  percent / 10 #=> Percent.new(5)
52
57
  ```
53
58
 
59
+ And with the number on the other side...
60
+
61
+ ``` ruby
62
+ percent = Percent.new(50)
63
+ 10 + percent #=> 15
64
+ 10 - percent #=> 5
65
+ 10 * percent #=> 5
66
+ 10 / percent #=> 20
67
+ ```
68
+
54
69
  Repeat steps above for Floats, BigDecimals, etc. It should all work.
55
70
 
56
71
  ### Can I turn other Numerics into Percents?
@@ -87,7 +102,7 @@ class OriginalClass
87
102
  end
88
103
  end
89
104
 
90
- class PercentizedClass
105
+ class PercentizedClass < OriginalClass
91
106
  extend Percentable::Percentize
92
107
 
93
108
  percentize :returns_a_percent
@@ -97,13 +112,41 @@ percentize_object = PercentizedClass.new
97
112
  percentize_object.returns_a_percent #=> Percent.new(10)
98
113
  ```
99
114
 
115
+ You can do percentize multiple methods at a time:
116
+
117
+ ``` ruby
118
+ class PercentizedClass < OriginalClass
119
+ extend Percentable::Percentize
120
+
121
+ percentize :method1, :method2
122
+ end
123
+ ```
124
+
125
+ You can define defaults for when the percentized method returns nil:
126
+
127
+ ``` ruby
128
+ class PercentizedClass < OriginalClass
129
+ extend Percentable::Percentize
130
+
131
+ percentize :method1, :method2, default: 20
132
+ end
133
+
134
+ # assuming method1 on OriginalClass returns nil
135
+ percentize_object = PercentizedClass.new
136
+ percentize_object.method1 #=> Percent.new(20)
137
+ ```
138
+
100
139
  ### OK, but why would I want this?
101
140
 
102
141
  I don't know, all I can tell you is that I found it useful. Instead of writing methods to translate from 0.1 to 10% all over the place, I now have a class to represent everything to do with percents.
103
142
 
104
143
  ### Is that it?
105
144
 
106
- Hey, I only wrote this in a night. Happy to except contributions from others!
145
+ Hey, I only wrote this in a night. Happy to accept contributions from others!
146
+
147
+ ### Your math is totally wrong and you are an idiot.
148
+
149
+ That's not a question. I've had a fair bit of discussion with the fine folks at [Boltmade](http://www.boltmade.com) about how it should behave, and the examples you see above are what we settled on. If you would like to propose a change, the best way would be to edit the README to show examples for how you would like it to act. You can also submit a pull request that changes the code, but if you submit the README first we can have a discussion about whether or not it makes sense. I'm not totally sold on the current implementation and would be happy to discuss changes.
107
150
 
108
151
  ## Contributing
109
152
 
@@ -21,9 +21,18 @@ module Percentable
21
21
  end
22
22
 
23
23
  def coerce other
24
+ method = caller[0].match("`(.+)'")[1].to_sym
25
+
24
26
  case other
25
27
  when Numeric
26
- [to_f, other]
28
+ case method
29
+ when :+
30
+ [to_f * other, other]
31
+ when :-
32
+ [other, to_f * other]
33
+ else
34
+ [other, to_f]
35
+ end
27
36
  else
28
37
  fail TypeError, "#{self.class} can't be coerced into #{other.class}"
29
38
  end
@@ -41,39 +50,32 @@ module Percentable
41
50
  to_f <=> other.to_f
42
51
  end
43
52
 
44
- def + other
45
- case other
46
- when Percent
47
- self.class.new(other.value + value)
48
- when Numeric
49
- self.class.new(other + value)
50
- end
51
- end
52
-
53
53
  def * other
54
54
  case other
55
55
  when Percent
56
- self.class.new(other.value * value)
56
+ self.class.new(to_f * other.value)
57
57
  when Numeric
58
- self.class.new(other * value)
58
+ self.class.new(value * other)
59
59
  end
60
60
  end
61
61
 
62
- def - other
63
- case other
64
- when Percent
65
- self.class.new(value - other.value)
66
- when Numeric
67
- self.class.new(value - other)
62
+ [:+, :-, :/].each do |operator|
63
+ define_method operator do |other|
64
+ case other
65
+ when Percent
66
+ self.class.new(value.public_send(operator, other.value))
67
+ when Numeric
68
+ self.class.new(value.public_send(operator, other))
69
+ end
68
70
  end
69
71
  end
70
72
 
71
- def / other
72
- case other
73
- when Percent
74
- self.class.new(value / other.value)
73
+ def self.from_numeric(numeric)
74
+ case numeric
75
75
  when Numeric
76
- self.class.new(value / other)
76
+ Percent.new(numeric*100)
77
+ else
78
+ fail TypeError, 'must inherit from Numeric'
77
79
  end
78
80
  end
79
81
  end
@@ -1,8 +1,12 @@
1
1
  module Percentable
2
2
  module Percentize
3
- def percentize field
4
- define_method(field) do |args=[]|
5
- Percent.new(super(*args))
3
+ def percentize *args
4
+ options = args.pop if args.last.is_a? Hash
5
+
6
+ args.each do |method_name|
7
+ define_method(method_name) do |args=[]|
8
+ Percent.new(super(*args) || options[:default])
9
+ end
6
10
  end
7
11
  end
8
12
  end
@@ -1,3 +1,3 @@
1
1
  module Percentable
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -21,4 +21,5 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.6"
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "rspec", "~> 3.0"
24
+ spec.add_development_dependency "coveralls"
24
25
  end
@@ -1,4 +1,5 @@
1
- require 'percentable/numeric'
1
+ require 'spec_helper'
2
+ require 'percentable'
2
3
  require 'bigdecimal'
3
4
 
4
5
  describe Numeric do
@@ -1,4 +1,6 @@
1
- require 'percentable/percent'
1
+ require 'spec_helper'
2
+ require 'bigdecimal'
3
+ require 'percentable'
2
4
 
3
5
  describe Percentable::Percent do
4
6
  subject { Percentable::Percent.new(value) }
@@ -68,6 +70,48 @@ describe Percentable::Percent do
68
70
  end
69
71
  end
70
72
 
73
+ describe '#to_i' do
74
+ [0.1, 0.5, 1, 1.8, 2, 2.2].each do |value|
75
+ context "value of #{value}" do
76
+ let(:value) { value }
77
+
78
+ it "should return #{value.floor} for #{value}" do
79
+ expect(subject.to_i).to eq value.floor
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ describe '#coerce' do
86
+ context 'when other is non numeric' do
87
+ let(:other) { 'string' }
88
+
89
+ it 'should raise a TypeError' do
90
+ expect { subject.coerce(other) }.to raise_error TypeError
91
+ end
92
+ end
93
+
94
+ context 'math' do
95
+ let(:value) { 50 }
96
+
97
+ it 'should add the value of percent*number' do
98
+ expect(10 + subject).to eq 15
99
+ end
100
+
101
+ it 'should subtract the value of percent*number' do
102
+ expect(10 - subject).to eq 5
103
+ end
104
+
105
+ it 'should multiply by the float value of the percent' do
106
+ expect(10 * subject).to eq 5
107
+ end
108
+
109
+ it 'should divide by the float value of the percent' do
110
+ expect(10 / subject).to eq 20
111
+ end
112
+ end
113
+ end
114
+
71
115
  shared_examples 'it is equal' do |equal_method|
72
116
  it 'should consider itself equal to other percents with the same value' do
73
117
  percent1 = subject.class.new(50)
@@ -153,11 +197,11 @@ describe Percentable::Percent do
153
197
 
154
198
  describe '#*' do
155
199
  context 'multiplying percents' do
156
- let(:percent1) { subject.class.new(9) }
157
- let(:percent2) { subject.class.new(9) }
200
+ let(:percent1) { subject.class.new(10) }
201
+ let(:percent2) { subject.class.new(10) }
158
202
 
159
203
  it 'should return the result of multiplying the percents' do
160
- expect(percent1 * percent2).to eq subject.class.new(81)
204
+ expect(percent1 * percent2).to eq subject.class.new(1)
161
205
  end
162
206
  end
163
207
 
@@ -232,4 +276,24 @@ describe Percentable::Percent do
232
276
  end
233
277
  end
234
278
  end
279
+
280
+ describe '.from_numeric' do
281
+ let(:n) { 0.5 }
282
+
283
+ it 'should multiply the input by 100 and return a percent for that value' do
284
+ expect(subject.class.from_numeric(n)).to eq Percent.new(50)
285
+ end
286
+
287
+ it 'should be considered equal to the numeric it was passed' do
288
+ expect(subject.class.from_numeric(n)).to eq n
289
+ end
290
+
291
+ context 'when passed a string' do
292
+ let(:n) { 'string' }
293
+
294
+ it 'should raise an argument error' do
295
+ expect { subject.class.from_numeric(n) }.to raise_error TypeError
296
+ end
297
+ end
298
+ end
235
299
  end
@@ -1,22 +1,78 @@
1
- require 'percentable/percent'
2
- require 'percentable/percentize'
1
+ require 'spec_helper'
2
+ require 'percentable'
3
3
 
4
4
  class TestClass
5
5
  def returns_a_percent
6
6
  10
7
7
  end
8
+
9
+ def first_percent_method
10
+ 15
11
+ end
12
+
13
+ def second_percent_method
14
+ 20
15
+ end
16
+
17
+ def default_percent_method
18
+ end
19
+
20
+ def default_filled_percent_method
21
+ 100
22
+ end
23
+
24
+ def default_percent_method1
25
+ end
26
+
27
+ def default_percent_method2
28
+ end
29
+
30
+ def default_percent_method3
31
+ 20.5
32
+ end
8
33
  end
9
34
 
10
35
  class Subject < TestClass
11
36
  extend Percentable::Percentize
12
37
 
13
38
  percentize :returns_a_percent
39
+ percentize :first_percent_method, :second_percent_method
40
+ percentize :default_percent_method, default: 10
41
+ percentize :default_filled_percent_method, default: 20
42
+ percentize :default_percent_method1, :default_percent_method2, :default_percent_method3, default: 20
14
43
  end
15
44
 
16
45
  describe Percentable::Percentize do
17
46
  subject { Subject.new }
47
+ let(:ancestor) { TestClass.new }
48
+
49
+ [:returns_a_percent, :first_percent_method, :second_percent_method].each do |method|
50
+ it 'should return a percent with value of TestClass' do
51
+ expect(subject.public_send(method)).to eq Percentable::Percent.new(ancestor.send(method))
52
+ end
53
+ end
54
+
55
+ context 'when passed a default value' do
56
+ it 'should return the default value when return value is nil' do
57
+ expect(subject.default_percent_method).to eq Percentable::Percent.new(10)
58
+ end
59
+
60
+ it 'should not return the default if the value is defined' do
61
+ expect(subject.default_filled_percent_method).to eq Percentable::Percent.new(100)
62
+ end
63
+
64
+ context 'with multiple methods' do
65
+ it 'should return the default value when return value is nil' do
66
+ expect(subject.default_percent_method1).to eq Percentable::Percent.new(20)
67
+ end
68
+
69
+ it 'should return the default value when return value is nil' do
70
+ expect(subject.default_percent_method2).to eq Percentable::Percent.new(20)
71
+ end
18
72
 
19
- it 'should return a percent with value of TestClass' do
20
- expect(subject.returns_a_percent).to eq Percentable::Percent.new(10)
73
+ it 'should not return the default when the value is set' do
74
+ expect(subject.default_percent_method3).to eq Percentable::Percent.new(20.5)
75
+ end
76
+ end
21
77
  end
22
78
  end
@@ -0,0 +1,2 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: percentable
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
  - Eric Roberts
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: coveralls
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: Small gem to make working with percents easier. Includes methods to make
56
70
  selected rails attributes return percents.
57
71
  email:
@@ -76,6 +90,7 @@ files:
76
90
  - spec/lib/percentable/numeric_spec.rb
77
91
  - spec/lib/percentable/percent_spec.rb
78
92
  - spec/lib/percentable/percentize_spec.rb
93
+ - spec/spec_helper.rb
79
94
  homepage: https://github.com/ericroberts/percentable
80
95
  licenses:
81
96
  - MIT
@@ -104,3 +119,4 @@ test_files:
104
119
  - spec/lib/percentable/numeric_spec.rb
105
120
  - spec/lib/percentable/percent_spec.rb
106
121
  - spec/lib/percentable/percentize_spec.rb
122
+ - spec/spec_helper.rb