cashrb 1.1.1 → 1.2.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.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ cashrb v1.2.0
2
+ =============
3
+ - allow creation using decimal values instead of cents if you'd rather
4
+
1
5
  cashrb v1.1.1
2
6
  =============
3
7
  - fix bug in #to_s/#to_f regarding negative amounts
data/README.md CHANGED
@@ -14,6 +14,17 @@ Usage
14
14
  n.to_s #=> "1.00"
15
15
  n.to_f #=> 1.0
16
16
 
17
+ # Don't like passing cents, set :from => :decimal and use a decimal value
18
+ n = Cash.new(1.11, from: :decimal)
19
+ n.cents #=> 111
20
+ n.to_s #=> "1.11"
21
+ n.to_f #=> 1.11
22
+
23
+ # Hate cents and always want to pass a decimal, just set the default
24
+ Cash.default_from = :decimal
25
+ n = Cash.new(1.11)
26
+ n.cents #=> 111
27
+
17
28
  # Define currency as you see fit.
18
29
  a = Cash.new(100, currency: :usd)
19
30
  b = Cash.new(100, currency: :eur)
data/cashrb.gemspec CHANGED
@@ -1,10 +1,10 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cashrb"
3
- s.version = "1.1.1"
3
+ s.version = "1.2.0"
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.authors = ["Shane Emmons"]
6
6
  s.email = ["semmons99@gmail.com"]
7
- s.homepage = "http://github.com/semmons99/cashrb"
7
+ s.homepage = "http://semmons99.github.com/cashrb/"
8
8
  s.summary = "Dead simple gem to work with Money/Currency without the hassle of Floats"
9
9
  s.description = "Dead simple gem to work with Money/Currency without the hassle of Floats"
10
10
 
data/lib/cashrb/cash.rb CHANGED
@@ -10,28 +10,60 @@ class Cash
10
10
  DEFAULT_CENTS_IN_WHOLE = 100
11
11
  DEFAULT_ROUNDING_METHOD = BigDecimal::ROUND_HALF_UP
12
12
  DEFAULT_CURRENCY = nil
13
+ DEFAULT_FROM = :cents
14
+
15
+ VALID_FROMS = [:cents, :decimal]
13
16
 
14
17
  CURRENCY_AWARE_METHODS = [:+, :-, :/, :%, :divmod, :<=>]
15
18
 
16
19
  class << self
17
- attr_accessor :default_cents_in_whole
18
- attr_accessor :default_rounding_method
19
- attr_accessor :default_currency
20
-
21
20
  def reset_defaults
22
21
  @default_cents_in_whole = DEFAULT_CENTS_IN_WHOLE
23
22
  @default_rounding_method = DEFAULT_ROUNDING_METHOD
24
23
  @default_currency = DEFAULT_CURRENCY
24
+ @default_from = DEFAULT_FROM
25
+ end
26
+
27
+ def valid_from?(from)
28
+ VALID_FROMS.include? from
29
+ end
30
+
31
+ def bd(val)
32
+ BigDecimal(val.to_s)
33
+ end
34
+
35
+ attr_accessor :default_cents_in_whole
36
+ attr_accessor :default_rounding_method
37
+ attr_accessor :default_currency
38
+ attr_reader :default_from
39
+
40
+ def default_from=(from)
41
+ unless valid_from? from
42
+ raise ArgumentError,
43
+ "invalid ':from'. valid values are #{VALID_FROMS.join(",")}"
44
+ end
45
+ @default_from = from
25
46
  end
26
47
  end
27
48
 
28
49
  reset_defaults
29
50
 
51
+ BD_ONE = bd(1)
52
+ BD_TEN = bd(10)
53
+
30
54
  attr_reader :currency
31
55
 
32
- def initialize(cents = 0, options = {})
33
- parse_initialize_options(options)
34
- @cents = bd(cents).round(0, @rounding_method)
56
+ def initialize(amt = 0, options = {})
57
+ opts = parse_initialize_options(options)
58
+ @cents = bd(amt)
59
+
60
+ if opts[:from] == :decimal
61
+ dollars, cents = @cents.divmod(BD_ONE)
62
+ @cents = (dollars * @cents_in_whole)
63
+ @cents += (cents * (BD_TEN ** @decimal_places))
64
+ end
65
+
66
+ @cents = @cents.round(0, @rounding_method)
35
67
  end
36
68
 
37
69
  def cents
@@ -99,7 +131,7 @@ class Cash
99
131
  private
100
132
 
101
133
  def bd(val)
102
- BigDecimal(val.to_s)
134
+ self.class.bd(val)
103
135
  end
104
136
 
105
137
  def dollars_and_cents
@@ -116,17 +148,24 @@ class Cash
116
148
  :cents_in_whole => self.class.default_cents_in_whole,
117
149
  :rounding_method => self.class.default_rounding_method,
118
150
  :currency => self.class.default_currency,
151
+ :from => self.class.default_from
119
152
  }.merge(options)
120
153
 
121
154
  @currency = opts[:currency]
122
155
  @cents_in_whole = if @currency.respond_to? :cents_in_whole
123
- @currency.cents_in_whole
156
+ bd(@currency.cents_in_whole)
124
157
  else
125
- opts[:cents_in_whole]
158
+ bd(opts[:cents_in_whole])
126
159
  end
127
160
  @decimal_places = decimal_places(@cents_in_whole)
128
161
  @rounding_method = opts[:rounding_method]
129
- nil
162
+
163
+ unless self.class.valid_from? opts[:from]
164
+ raise ArgumentError,
165
+ "invalid ':from'. valid values are #{VALID_FROMS.join(",")}"
166
+ end
167
+
168
+ opts
130
169
  end
131
170
 
132
171
  def decimal_places(cents_in_whole)
data/test/test_cash.rb CHANGED
@@ -29,6 +29,19 @@ class TestCash < MiniTest::Unit::TestCase
29
29
  assert_equal :usd, rs.currency
30
30
  end
31
31
 
32
+ def test_default_from
33
+ Cash.default_from = :decimal
34
+
35
+ rs = Cash.new(1.11)
36
+ assert_equal 111, rs.cents
37
+ end
38
+
39
+ def test_invalid_default_from
40
+ assert_raises ArgumentError do
41
+ Cash.default_from = :foo
42
+ end
43
+ end
44
+
32
45
  def test_new
33
46
  rs = Cash.new(100)
34
47
  assert_equal 100, rs.cents
@@ -58,6 +71,67 @@ class TestCash < MiniTest::Unit::TestCase
58
71
  assert_equal 0.9, rs.to_f
59
72
  end
60
73
 
74
+ def test_new_with_from
75
+ rs = Cash.new(111, :from => :cents)
76
+ assert_equal 111, rs.cents
77
+
78
+ rs = Cash.new(1.11, :from => :decimal)
79
+ assert_equal 111, rs.cents
80
+ end
81
+
82
+ def test_new_with_from_and_cents_in_whole
83
+ rs = Cash.new(111, :from => :cents, :cents_in_whole => 1)
84
+ assert_equal 111, rs.cents
85
+
86
+ rs = Cash.new(111, :from => :cents, :cents_in_whole => 5)
87
+ assert_equal 111, rs.cents
88
+
89
+ rs = Cash.new(111, :from => :cents, :cents_in_whole => 10)
90
+ assert_equal 111, rs.cents
91
+
92
+ rs = Cash.new(111, :from => :cents, :cents_in_whole => 100)
93
+ assert_equal 111, rs.cents
94
+
95
+ rs = Cash.new(111, :from => :cents, :cents_in_whole => 1000)
96
+ assert_equal 111, rs.cents
97
+
98
+ rs = Cash.new(1.0, :from => :decimal, :cents_in_whole => 1)
99
+ assert_equal 1, rs.cents
100
+
101
+ rs = Cash.new(1.1, :from => :decimal, :cents_in_whole => 5)
102
+ assert_equal 6, rs.cents
103
+
104
+ rs = Cash.new(1.1, :from => :decimal, :cents_in_whole => 10)
105
+ assert_equal 11, rs.cents
106
+
107
+ rs = Cash.new(1.11, :from => :decimal, :cents_in_whole => 100)
108
+ assert_equal 111, rs.cents
109
+
110
+ rs = Cash.new(1.01, :from => :decimal, :cents_in_whole => 100)
111
+ assert_equal 101, rs.cents
112
+
113
+ rs = Cash.new(1.00, :from => :decimal, :cents_in_whole => 100)
114
+ assert_equal 100, rs.cents
115
+
116
+ rs = Cash.new(1.111, :from => :decimal, :cents_in_whole => 1000)
117
+ assert_equal 1111, rs.cents
118
+
119
+ rs = Cash.new(1.011, :from => :decimal, :cents_in_whole => 1000)
120
+ assert_equal 1011, rs.cents
121
+
122
+ rs = Cash.new(1.001, :from => :decimal, :cents_in_whole => 1000)
123
+ assert_equal 1001, rs.cents
124
+
125
+ rs = Cash.new(1.000, :from => :decimal, :cents_in_whole => 1000)
126
+ assert_equal 1000, rs.cents
127
+ end
128
+
129
+ def test_new_with_invalid_from
130
+ assert_raises ArgumentError do
131
+ Cash.new(1, :from => :foo)
132
+ end
133
+ end
134
+
61
135
  def test_plus_with_Cash_Cash
62
136
  rs = Cash.new(6) + Cash.new(4)
63
137
  assert_equal Cash.new(10), rs
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cashrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-04-08 00:00:00.000000000Z
12
+ date: 2011-04-12 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description: Dead simple gem to work with Money/Currency without the hassle of Floats
15
15
  email:
@@ -27,7 +27,7 @@ files:
27
27
  - Rakefile
28
28
  - .gemtest
29
29
  - cashrb.gemspec
30
- homepage: http://github.com/semmons99/cashrb
30
+ homepage: http://semmons99.github.com/cashrb/
31
31
  licenses: []
32
32
  post_install_message:
33
33
  rdoc_options: []