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