cashrb 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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: []