money 6.0.0.pre2 → 6.0.0.pre3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +19 -0
- data/config/currency_iso.json +1 -1
- data/lib/money/money.rb +48 -27
- data/lib/money/money/arithmetic.rb +28 -30
- data/lib/money/money/formatting.rb +25 -8
- data/money.gemspec +12 -1
- data/spec/money/arithmetic_spec.rb +55 -6
- data/spec/money/formatting_spec.rb +35 -2
- data/spec/money/parsing_spec.rb +2 -2
- data/spec/money_spec.rb +69 -2
- metadata +16 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9dae4831f4901cf906ae3d6f155c9bac6e3f67f
|
4
|
+
data.tar.gz: 43718a7d7edfce6329053cd90a7b61ec2d4d3a78
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a13f5e9078a642608bc4d224639b27ca74b44952c6cba8790515534c5e09d50d77eba86c4f0fc0540fb4d840cf8b9c3cef6ef8af6a06fb5c81740850862e971e
|
7
|
+
data.tar.gz: 652d159f7d083c9975f15ad14f3f92cd2aea19c475cacc3dead90711771d5ed04b32e96a66b97b08ee3153816670037088a8ad8fb49f2c5b552b8336a2dde2af
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
3
|
## master
|
4
|
+
- New option :sign_positive to add a + sign to positive numbers
|
5
|
+
- Only allow to multiply a money by a number (int, float)
|
4
6
|
- Fix typo
|
5
7
|
- Wrap the currency symbol in a span if :html is specified in the rules
|
6
8
|
- Added Money::Currency.all method
|
@@ -9,6 +11,14 @@
|
|
9
11
|
- Works on Ruby 1.8.7
|
10
12
|
- Update deps
|
11
13
|
- Depreciate Money.parse
|
14
|
+
- Passing :symbol => false when formatting 'JPY' currency in :ja locale
|
15
|
+
will work as expected
|
16
|
+
- Divide now obeys the specified rounding mode
|
17
|
+
- Add Money#round method. This is helpful when working in infinite_precision mode and would like to perform rounding at specific points in your work flow.
|
18
|
+
- In infinite precision mode, deserialized Money objects no longer return Float values from the `fractional` method.
|
19
|
+
- Changed `thousands_separator` for Swedish Krona from dot to blank space.
|
20
|
+
- Allow mathematical operations with first argument being not an instance of Money (eg. 2 * money instead of money * 2).
|
21
|
+
- Money#dollars and Money#amount methods return numbers of type BigDecimal.
|
12
22
|
|
13
23
|
## 5.1.1
|
14
24
|
|
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/money.png)](http://badge.fury.io/rb/money) [![Build Status](https://travis-ci.org/RubyMoney/money.png?branch=master)](https://travis-ci.org/RubyMoney/money) [![Code Climate](https://codeclimate.com/github/RubyMoney/money.png)](https://codeclimate.com/github/RubyMoney/money)
|
4
4
|
|
5
|
+
:warning: Please read the [migration notes](#migration-notes) before upgrading to a new major version.
|
6
|
+
|
5
7
|
## Contributing
|
6
8
|
|
7
9
|
See the [Contribution Guidelines](https://github.com/RubyMoney/money/blob/master/CONTRIBUTING.md)
|
@@ -249,9 +251,26 @@ implementations.
|
|
249
251
|
- [nbrb_currency](https://github.com/slbug/nbrb_currency)
|
250
252
|
- [money-open-exchange-rates](https://github.com/spk/money-open-exchange-rates)
|
251
253
|
- [money-historical-bank](https://github.com/atwam/money-historical-bank)
|
254
|
+
- [russian_central_bank](https://github.com/rmustafin/russian_central_bank)
|
252
255
|
|
253
256
|
## Ruby on Rails
|
254
257
|
|
255
258
|
To integrate money in a Rails application use [money-rails](http://github.com/RubyMoney/money-rails).
|
256
259
|
|
257
260
|
For deprecated methods of integrating with Rails, check [the wiki](https://github.com/RubyMoney/money/wiki).
|
261
|
+
|
262
|
+
## Migration Notes
|
263
|
+
|
264
|
+
#### Version 6.0.0.pre3
|
265
|
+
|
266
|
+
- The `Money#dollars` and `Money#amount` methods now return instances of
|
267
|
+
`BigDecimal` rather than `Float`. We should avoid representing monetary
|
268
|
+
values with floating point types so to avoid a whole class of errors relating
|
269
|
+
to lack of precision. There are two migration options for this change:
|
270
|
+
* The first is to test your application and where applicable update the
|
271
|
+
application to accept a `BigDecimal` return value. This is the recommended
|
272
|
+
path.
|
273
|
+
* The second is to migrate from the `#amount` and `#dollars` methods to use
|
274
|
+
the `#to_f` method instead. This option should only be used where `Float`
|
275
|
+
is the desired type and nothing else will do for your application's
|
276
|
+
requirements.
|
data/config/currency_iso.json
CHANGED
data/lib/money/money.rb
CHANGED
@@ -22,16 +22,27 @@ class Money
|
|
22
22
|
#
|
23
23
|
# @return [Integer]
|
24
24
|
def fractional
|
25
|
+
# Ensure we have a BigDecimal. If the Money object is created
|
26
|
+
# from YAML, @fractional can end up being set to a Float.
|
27
|
+
fractional = as_d(@fractional)
|
28
|
+
|
25
29
|
if self.class.infinite_precision
|
26
|
-
|
30
|
+
fractional
|
31
|
+
else
|
32
|
+
fractional.round(0, self.class.rounding_mode).to_i
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def as_d(num)
|
37
|
+
if num.is_a?(Rational)
|
38
|
+
num.to_d(self.class.conversion_precision)
|
39
|
+
elsif num.respond_to?(:to_d)
|
40
|
+
num.to_d
|
27
41
|
else
|
28
|
-
|
29
|
-
# @fractional can end up being set to a Float. We need to ensure
|
30
|
-
# it is BigDecimal before calling #round with two paramers.
|
31
|
-
# Float class only provides #round with 0 or 1 parameter.
|
32
|
-
BigDecimal.new(@fractional.to_s, 0).round(0, self.class.rounding_mode).to_i
|
42
|
+
BigDecimal.new(num.to_s)
|
33
43
|
end
|
34
44
|
end
|
45
|
+
private :as_d
|
35
46
|
|
36
47
|
# The currency the money is in.
|
37
48
|
#
|
@@ -238,13 +249,7 @@ class Money
|
|
238
249
|
# @see Money.new_with_dollars
|
239
250
|
#
|
240
251
|
def initialize(fractional, currency = Money.default_currency, bank = Money.default_bank)
|
241
|
-
@fractional =
|
242
|
-
fractional.to_d(self.class.conversion_precision)
|
243
|
-
elsif fractional.respond_to?(:to_d)
|
244
|
-
fractional.to_d
|
245
|
-
else
|
246
|
-
BigDecimal.new(fractional.to_s)
|
247
|
-
end
|
252
|
+
@fractional = as_d(fractional)
|
248
253
|
@currency = Currency.wrap(currency)
|
249
254
|
@bank = bank
|
250
255
|
end
|
@@ -255,14 +260,14 @@ class Money
|
|
255
260
|
#
|
256
261
|
# Synonym of #amount
|
257
262
|
#
|
258
|
-
# @return [
|
263
|
+
# @return [BigDecimal]
|
259
264
|
#
|
260
265
|
# @example
|
261
266
|
# Money.new(100).dollars # => 1.0
|
262
267
|
# Money.new_with_dollars(1).dollar # => 1.0
|
263
268
|
#
|
264
269
|
# @see #amount
|
265
|
-
# @see #
|
270
|
+
# @see #to_d
|
266
271
|
# @see #cents
|
267
272
|
#
|
268
273
|
def dollars
|
@@ -271,17 +276,17 @@ class Money
|
|
271
276
|
|
272
277
|
# Returns the numerical value of the money
|
273
278
|
#
|
274
|
-
# @return [
|
279
|
+
# @return [BigDecimal]
|
275
280
|
#
|
276
281
|
# @example
|
277
282
|
# Money.new(100).amount # => 1.0
|
278
283
|
# Money.new_with_amount(1).amount # => 1.0
|
279
284
|
#
|
280
|
-
# @see #
|
285
|
+
# @see #to_d
|
281
286
|
# @see #fractional
|
282
287
|
#
|
283
288
|
def amount
|
284
|
-
|
289
|
+
to_d
|
285
290
|
end
|
286
291
|
|
287
292
|
# Return string representation of currency object
|
@@ -385,13 +390,13 @@ class Money
|
|
385
390
|
# @example
|
386
391
|
# Money.us_dollar(100).to_d => BigDecimal.new("1.0")
|
387
392
|
def to_d
|
388
|
-
|
393
|
+
as_d(fractional) / as_d(currency.subunit_to_unit)
|
389
394
|
end
|
390
395
|
|
391
396
|
# Return the amount of money as a float. Floating points cannot guarantee
|
392
397
|
# precision. Therefore, this function should only be used when you no longer
|
393
398
|
# need to represent currency or working with another system that requires
|
394
|
-
#
|
399
|
+
# floats.
|
395
400
|
#
|
396
401
|
# @return [Float]
|
397
402
|
#
|
@@ -476,10 +481,7 @@ class Money
|
|
476
481
|
# Money.new(5, "USD").allocate([0.3,0.7)) #=> [Money.new(2), Money.new(3)]
|
477
482
|
# Money.new(100, "USD").allocate([0.33,0.33,0.33]) #=> [Money.new(34), Money.new(33), Money.new(33)]
|
478
483
|
def allocate(splits)
|
479
|
-
allocations = splits.inject(
|
480
|
-
n = BigDecimal(n.to_s) unless n.is_a?(BigDecimal)
|
481
|
-
sum + n
|
482
|
-
end
|
484
|
+
allocations = splits.inject(0) { |sum, n| sum + as_d(n) }
|
483
485
|
|
484
486
|
if (allocations - BigDecimal("1")) > Float::EPSILON
|
485
487
|
raise ArgumentError, "splits add to more then 100%"
|
@@ -516,12 +518,12 @@ class Money
|
|
516
518
|
raise ArgumentError, "need at least one party" if num < 1
|
517
519
|
|
518
520
|
if self.class.infinite_precision
|
519
|
-
amt =
|
521
|
+
amt = div(as_d(num))
|
520
522
|
return 1.upto(num).map{amt}
|
521
523
|
end
|
522
524
|
|
523
|
-
low = Money.new(fractional / num,
|
524
|
-
high = Money.new(low.fractional + 1,
|
525
|
+
low = Money.new(fractional / num, currency)
|
526
|
+
high = Money.new(low.fractional + 1, currency)
|
525
527
|
|
526
528
|
remainder = fractional % num
|
527
529
|
result = []
|
@@ -533,4 +535,23 @@ class Money
|
|
533
535
|
result
|
534
536
|
end
|
535
537
|
|
538
|
+
# Round the monetary amount to smallest unit of coinage.
|
539
|
+
#
|
540
|
+
# This method is only useful when operating with infinite_precision turned
|
541
|
+
# on. Without infinite_precision values are rounded to the smallest unit of
|
542
|
+
# coinage automatically.
|
543
|
+
#
|
544
|
+
# @return [Money]
|
545
|
+
#
|
546
|
+
# @example
|
547
|
+
# Money.new(10.1, 'USD').round #=> Money.new(10, 'USD')
|
548
|
+
#
|
549
|
+
def round(rounding_mode = self.class.rounding_mode)
|
550
|
+
if self.class.infinite_precision
|
551
|
+
return Money.new(fractional.round(0, rounding_mode), self.currency)
|
552
|
+
else
|
553
|
+
return self
|
554
|
+
end
|
555
|
+
end
|
556
|
+
|
536
557
|
end
|
@@ -26,7 +26,7 @@ class Money
|
|
26
26
|
def ==(other_money)
|
27
27
|
if other_money.respond_to?(:to_money)
|
28
28
|
other_money = other_money.to_money
|
29
|
-
fractional == other_money.fractional &&
|
29
|
+
fractional == other_money.fractional && currency == other_money.currency
|
30
30
|
else
|
31
31
|
false
|
32
32
|
end
|
@@ -93,11 +93,8 @@ class Money
|
|
93
93
|
# @example
|
94
94
|
# Money.new(100) + Money.new(100) #=> #<Money @fractional=200>
|
95
95
|
def +(other_money)
|
96
|
-
|
97
|
-
|
98
|
-
else
|
99
|
-
Money.new(fractional + other_money.exchange_to(currency).fractional, currency)
|
100
|
-
end
|
96
|
+
other_money = other_money.exchange_to(currency)
|
97
|
+
Money.new(fractional + other_money.fractional, currency)
|
101
98
|
end
|
102
99
|
|
103
100
|
# Returns a new Money object containing the difference between the two
|
@@ -112,11 +109,8 @@ class Money
|
|
112
109
|
# @example
|
113
110
|
# Money.new(100) - Money.new(99) #=> #<Money @fractional=1>
|
114
111
|
def -(other_money)
|
115
|
-
|
116
|
-
|
117
|
-
else
|
118
|
-
Money.new(fractional - other_money.exchange_to(currency).fractional, currency)
|
119
|
-
end
|
112
|
+
other_money = other_money.exchange_to(currency)
|
113
|
+
Money.new(fractional - other_money.fractional, currency)
|
120
114
|
end
|
121
115
|
|
122
116
|
# Multiplies the monetary value with the given number and returns a new
|
@@ -128,16 +122,16 @@ class Money
|
|
128
122
|
#
|
129
123
|
# @return [Money] The resulting money.
|
130
124
|
#
|
131
|
-
# @raise [ArgumentError] If +value+ is a
|
125
|
+
# @raise [ArgumentError] If +value+ is NOT a number.
|
132
126
|
#
|
133
127
|
# @example
|
134
128
|
# Money.new(100) * 2 #=> #<Money @fractional=200>
|
135
129
|
#
|
136
130
|
def *(value)
|
137
|
-
if value.is_a?
|
138
|
-
raise ArgumentError, "Can't multiply a Money by a Money"
|
139
|
-
else
|
131
|
+
if value.is_a? Numeric
|
140
132
|
Money.new(fractional * value, currency)
|
133
|
+
else
|
134
|
+
raise ArgumentError, "Can't multiply a Money by a #{value.class.name}'s value"
|
141
135
|
end
|
142
136
|
end
|
143
137
|
|
@@ -158,13 +152,9 @@ class Money
|
|
158
152
|
#
|
159
153
|
def /(value)
|
160
154
|
if value.is_a?(Money)
|
161
|
-
|
162
|
-
(fractional / BigDecimal.new(value.fractional.to_s)).to_f
|
163
|
-
else
|
164
|
-
(fractional / BigDecimal(value.exchange_to(currency).fractional.to_s)).to_f
|
165
|
-
end
|
155
|
+
fractional / as_d(value.exchange_to(currency).fractional).to_f
|
166
156
|
else
|
167
|
-
Money.new(fractional / value, currency)
|
157
|
+
Money.new(fractional / as_d(value), currency)
|
168
158
|
end
|
169
159
|
end
|
170
160
|
|
@@ -193,16 +183,16 @@ class Money
|
|
193
183
|
# Money.new(100).divmod(Money.new(9)) #=> [11, #<Money @fractional=1>]
|
194
184
|
def divmod(val)
|
195
185
|
if val.is_a?(Money)
|
196
|
-
a =
|
197
|
-
b =
|
186
|
+
a = fractional
|
187
|
+
b = val.exchange_to(currency).cents
|
198
188
|
q, m = a.divmod(b)
|
199
|
-
return [q, Money.new(m,
|
189
|
+
return [q, Money.new(m, currency)]
|
200
190
|
else
|
201
191
|
if self.class.infinite_precision
|
202
|
-
q, m =
|
203
|
-
return [Money.new(q,
|
192
|
+
q, m = fractional.divmod(as_d(val))
|
193
|
+
return [Money.new(q, currency), Money.new(m, currency)]
|
204
194
|
else
|
205
|
-
return [
|
195
|
+
return [div(val), Money.new(fractional.modulo(val), currency)]
|
206
196
|
end
|
207
197
|
end
|
208
198
|
end
|
@@ -217,7 +207,7 @@ class Money
|
|
217
207
|
# Money.new(100).modulo(9) #=> #<Money @fractional=1>
|
218
208
|
# Money.new(100).modulo(Money.new(9)) #=> #<Money @fractional=1>
|
219
209
|
def modulo(val)
|
220
|
-
|
210
|
+
divmod(val)[1]
|
221
211
|
end
|
222
212
|
|
223
213
|
# Synonym for +#modulo+.
|
@@ -228,7 +218,7 @@ class Money
|
|
228
218
|
#
|
229
219
|
# @see #modulo
|
230
220
|
def %(val)
|
231
|
-
|
221
|
+
modulo(val)
|
232
222
|
end
|
233
223
|
|
234
224
|
# If different signs +self.modulo(val) - val+ otherwise +self.modulo(val)+
|
@@ -258,7 +248,7 @@ class Money
|
|
258
248
|
# @example
|
259
249
|
# Money.new(-100).abs #=> #<Money @fractional=100>
|
260
250
|
def abs
|
261
|
-
Money.new(
|
251
|
+
Money.new(fractional.abs, currency)
|
262
252
|
end
|
263
253
|
|
264
254
|
# Test if the money amount is zero.
|
@@ -284,5 +274,13 @@ class Money
|
|
284
274
|
fractional != 0 ? self : nil
|
285
275
|
end
|
286
276
|
|
277
|
+
# Used to make Money instance handle the operations when arguments order is reversed
|
278
|
+
# @return [Array]
|
279
|
+
#
|
280
|
+
# @example
|
281
|
+
# 2 * Money.new(10) #=> #<Money @fractional=20>
|
282
|
+
def coerce(other)
|
283
|
+
[self, other]
|
284
|
+
end
|
287
285
|
end
|
288
286
|
end
|
@@ -180,6 +180,18 @@ class Money
|
|
180
180
|
# Money.new(-100, "GBP").format(:sign_before_symbol => true) #=> "-£1.00"
|
181
181
|
# Money.new(-100, "GBP").format(:sign_before_symbol => false) #=> "£-1.00"
|
182
182
|
# Money.new(-100, "GBP").format #=> "£-1.00"
|
183
|
+
#
|
184
|
+
# @option *rules [Boolean] :sign_positive (false) Whether positive numbers should be
|
185
|
+
# signed, too.
|
186
|
+
#
|
187
|
+
# @example
|
188
|
+
# # You can specify to display the sign with positive numbers
|
189
|
+
# Money.new(100, "GBP").format(:sign_positive => true, :sign_before_symbol => true) #=> "+£1.00"
|
190
|
+
# Money.new(100, "GBP").format(:sign_positive => true, :sign_before_symbol => false) #=> "£+1.00"
|
191
|
+
# Money.new(100, "GBP").format(:sign_positive => false, :sign_before_symbol => true) #=> "£1.00"
|
192
|
+
# Money.new(100, "GBP").format(:sign_positive => false, :sign_before_symbol => false) #=> "£1.00"
|
193
|
+
# Money.new(100, "GBP").format #=> "£+1.00"
|
194
|
+
|
183
195
|
def format(*rules)
|
184
196
|
# support for old format parameters
|
185
197
|
rules = normalize_formatting_rules(rules)
|
@@ -208,7 +220,9 @@ class Money
|
|
208
220
|
symbol
|
209
221
|
end
|
210
222
|
|
211
|
-
|
223
|
+
sign = self.negative? ? '-' : ''
|
224
|
+
formatted = rules[:no_cents] ? "#{self.abs.to_s.to_i}" : self.abs.to_s
|
225
|
+
|
212
226
|
|
213
227
|
if rules[:no_cents_if_whole] && cents % currency.subunit_to_unit == 0
|
214
228
|
formatted = "#{self.to_s.to_i}"
|
@@ -233,10 +247,13 @@ class Money
|
|
233
247
|
:after
|
234
248
|
end
|
235
249
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
250
|
+
if rules[:sign_positive] == true && self.positive?
|
251
|
+
sign = '+'
|
252
|
+
end
|
253
|
+
|
254
|
+
if rules[:sign_before_symbol] == true
|
255
|
+
sign_before = sign
|
256
|
+
sign = ''
|
240
257
|
end
|
241
258
|
|
242
259
|
if symbol_value && !symbol_value.empty?
|
@@ -244,10 +261,10 @@ class Money
|
|
244
261
|
|
245
262
|
formatted = if symbol_position == :before
|
246
263
|
symbol_space = rules[:symbol_before_without_space] === false ? " " : ""
|
247
|
-
"#{
|
264
|
+
"#{sign_before}#{symbol_value}#{symbol_space}#{sign}#{formatted}"
|
248
265
|
else
|
249
266
|
symbol_space = rules[:symbol_after_without_space] ? "" : " "
|
250
|
-
"#{
|
267
|
+
"#{sign_before}#{formatted}#{symbol_space}#{sign}#{symbol_value}"
|
251
268
|
end
|
252
269
|
end
|
253
270
|
|
@@ -306,7 +323,7 @@ class Money
|
|
306
323
|
|
307
324
|
def localize_formatting_rules(rules)
|
308
325
|
if currency.iso_code == "JPY" && I18n.locale == :ja
|
309
|
-
rules[:symbol] = "円"
|
326
|
+
rules[:symbol] = "円" unless rules[:symbol] == false
|
310
327
|
rules[:symbol_position] = :after
|
311
328
|
rules[:symbol_after_without_space] = true
|
312
329
|
end
|
data/money.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
Gem::Specification.new do |s|
|
3
3
|
s.name = "money"
|
4
|
-
s.version = "6.0.0.
|
4
|
+
s.version = "6.0.0.pre3"
|
5
5
|
s.platform = Gem::Platform::RUBY
|
6
6
|
s.authors = ["Tobias Luetke", "Hongli Lai", "Jeremy McNevin",
|
7
7
|
"Shane Emmons", "Simone Carletti"]
|
@@ -10,6 +10,17 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.summary = "Money and currency exchange support library."
|
11
11
|
s.description = "This library aids one in handling money and different currencies."
|
12
12
|
|
13
|
+
s.post_install_message = '''
|
14
|
+
Please note the following API changes in Money version 6
|
15
|
+
|
16
|
+
- Money#amount, Money#dollars methods now return instances of BigDecimal (rather than Float).
|
17
|
+
|
18
|
+
Please read the migration notes at https://github.com/RubyMoney/money#migration-notes
|
19
|
+
and choose the migration that best suits your application.
|
20
|
+
|
21
|
+
Test responsibly :-)
|
22
|
+
'''
|
23
|
+
|
13
24
|
s.required_ruby_version = ">= 1.8.7"
|
14
25
|
|
15
26
|
s.add_dependency "i18n", "~> 0.6.4"
|
@@ -259,14 +259,18 @@ describe Money do
|
|
259
259
|
it "does not multiply Money by Money (different currency)" do
|
260
260
|
expect { Money.new( 10, :USD) * Money.new( 4, :EUR) }.to raise_error(ArgumentError)
|
261
261
|
end
|
262
|
+
|
263
|
+
it "does not multiply Money by an object which is NOT a number" do
|
264
|
+
expect { Money.new( 10, :USD) * 'abc' }.to raise_error(ArgumentError)
|
265
|
+
end
|
262
266
|
end
|
263
267
|
|
264
268
|
describe "#/" do
|
265
269
|
it "divides Money by Fixnum and returns Money" do
|
266
270
|
ts = [
|
267
271
|
{:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 3, :USD)},
|
268
|
-
{:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-
|
269
|
-
{:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-
|
272
|
+
{:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-3, :USD)},
|
273
|
+
{:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-3, :USD)},
|
270
274
|
{:a => Money.new(-13, :USD), :b => -4, :c => Money.new( 3, :USD)},
|
271
275
|
]
|
272
276
|
ts.each do |t|
|
@@ -274,6 +278,44 @@ describe Money do
|
|
274
278
|
end
|
275
279
|
end
|
276
280
|
|
281
|
+
context 'rounding preference' do
|
282
|
+
before do
|
283
|
+
Money.stub(:rounding_mode => rounding_mode)
|
284
|
+
end
|
285
|
+
|
286
|
+
after do
|
287
|
+
Money.unstub(:rounding_mode)
|
288
|
+
end
|
289
|
+
|
290
|
+
context 'ceiling rounding' do
|
291
|
+
let(:rounding_mode) { BigDecimal::ROUND_CEILING }
|
292
|
+
it "obeys the rounding preference" do
|
293
|
+
(Money.new(10) / 3).should == Money.new(4)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
context 'floor rounding' do
|
298
|
+
let(:rounding_mode) { BigDecimal::ROUND_FLOOR }
|
299
|
+
it "obeys the rounding preference" do
|
300
|
+
(Money.new(10) / 6).should == Money.new(1)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
context 'half up rounding' do
|
305
|
+
let(:rounding_mode) { BigDecimal::ROUND_HALF_UP }
|
306
|
+
it "obeys the rounding preference" do
|
307
|
+
(Money.new(10) / 4).should == Money.new(3)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
context 'half down rounding' do
|
312
|
+
let(:rounding_mode) { BigDecimal::ROUND_HALF_DOWN }
|
313
|
+
it "obeys the rounding preference" do
|
314
|
+
(Money.new(10) / 4).should == Money.new(2)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
277
319
|
it "divides Money by Money (same currency) and returns Float" do
|
278
320
|
ts = [
|
279
321
|
{:a => Money.new( 13, :USD), :b => Money.new( 4, :USD), :c => 3.25},
|
@@ -326,8 +368,8 @@ describe Money do
|
|
326
368
|
it "divides Money by Fixnum and returns Money" do
|
327
369
|
ts = [
|
328
370
|
{:a => Money.new( 13, :USD), :b => 4, :c => Money.new( 3, :USD)},
|
329
|
-
{:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-
|
330
|
-
{:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-
|
371
|
+
{:a => Money.new( 13, :USD), :b => -4, :c => Money.new(-3, :USD)},
|
372
|
+
{:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-3, :USD)},
|
331
373
|
{:a => Money.new(-13, :USD), :b => -4, :c => Money.new( 3, :USD)},
|
332
374
|
]
|
333
375
|
ts.each do |t|
|
@@ -387,8 +429,8 @@ describe Money do
|
|
387
429
|
it "calculates division and modulo with Fixnum" do
|
388
430
|
ts = [
|
389
431
|
{:a => Money.new( 13, :USD), :b => 4, :c => [Money.new( 3, :USD), Money.new( 1, :USD)]},
|
390
|
-
{:a => Money.new( 13, :USD), :b => -4, :c => [Money.new(-
|
391
|
-
{:a => Money.new(-13, :USD), :b => 4, :c => [Money.new(-
|
432
|
+
{:a => Money.new( 13, :USD), :b => -4, :c => [Money.new(-3, :USD), Money.new(-3, :USD)]},
|
433
|
+
{:a => Money.new(-13, :USD), :b => 4, :c => [Money.new(-3, :USD), Money.new( 3, :USD)]},
|
392
434
|
{:a => Money.new(-13, :USD), :b => -4, :c => [Money.new( 3, :USD), Money.new(-1, :USD)]},
|
393
435
|
]
|
394
436
|
ts.each do |t|
|
@@ -595,4 +637,11 @@ describe Money do
|
|
595
637
|
money.nonzero?.should be_equal(money)
|
596
638
|
end
|
597
639
|
end
|
640
|
+
|
641
|
+
describe "#coerce" do
|
642
|
+
it "allows mathematical operations by coercing arguments" do
|
643
|
+
result = 2 * Money.new(4, 'USD')
|
644
|
+
result.should == Money.new(8, 'USD')
|
645
|
+
end
|
646
|
+
end
|
598
647
|
end
|
@@ -82,7 +82,9 @@ describe Money, "formatting" do
|
|
82
82
|
before { @_locale = I18n.locale; I18n.locale = :ja }
|
83
83
|
|
84
84
|
it "formats Japanese currency in Japanese properly" do
|
85
|
-
Money.new(1000, "JPY")
|
85
|
+
money = Money.new(1000, "JPY")
|
86
|
+
money.format.should == "1,000円"
|
87
|
+
money.format(:symbol => false).should == "1,000"
|
86
88
|
end
|
87
89
|
|
88
90
|
after { I18n.locale = @_locale }
|
@@ -133,7 +135,7 @@ describe Money, "formatting" do
|
|
133
135
|
one_thousand["BRL"].should == "R$ 1.000,00"
|
134
136
|
|
135
137
|
# Other
|
136
|
-
one_thousand["SEK"].should == "1
|
138
|
+
one_thousand["SEK"].should == "1 000,00 kr"
|
137
139
|
one_thousand["GHC"].should == "₵1,000.00"
|
138
140
|
end
|
139
141
|
|
@@ -265,6 +267,9 @@ describe Money, "formatting" do
|
|
265
267
|
money.format(:symbol => "").should == "1.00"
|
266
268
|
money.format(:symbol => nil).should == "1.00"
|
267
269
|
money.format(:symbol => false).should == "1.00"
|
270
|
+
|
271
|
+
money = Money.new(100, "JPY")
|
272
|
+
money.format(:symbol => false).should == "100"
|
268
273
|
end
|
269
274
|
|
270
275
|
it "defaults :symbol to true" do
|
@@ -406,6 +411,34 @@ describe Money, "formatting" do
|
|
406
411
|
end
|
407
412
|
end
|
408
413
|
|
414
|
+
describe ":sign_positive option" do
|
415
|
+
specify "(:sign_positive => true, :sign_before_symbol => true) works as documented" do
|
416
|
+
Money.us_dollar( 0).format(:sign_positive => true, :sign_before_symbol => true).should == "$0.00"
|
417
|
+
Money.us_dollar( 100000).format(:sign_positive => true, :sign_before_symbol => true).should == "+$1,000.00"
|
418
|
+
Money.us_dollar(-100000).format(:sign_positive => true, :sign_before_symbol => true).should == "-$1,000.00"
|
419
|
+
end
|
420
|
+
|
421
|
+
specify "(:sign_positive => true, :sign_before_symbol => false) works as documented" do
|
422
|
+
Money.us_dollar( 0).format(:sign_positive => true, :sign_before_symbol => false).should == "$0.00"
|
423
|
+
Money.us_dollar( 100000).format(:sign_positive => true, :sign_before_symbol => false).should == "$+1,000.00"
|
424
|
+
Money.us_dollar( 100000).format(:sign_positive => true, :sign_before_symbol => nil).should == "$+1,000.00"
|
425
|
+
Money.us_dollar(-100000).format(:sign_positive => true, :sign_before_symbol => false).should == "$-1,000.00"
|
426
|
+
Money.us_dollar(-100000).format(:sign_positive => true, :sign_before_symbol => nil).should == "$-1,000.00"
|
427
|
+
end
|
428
|
+
|
429
|
+
specify "(:sign_positive => false, :sign_before_symbol => true) works as documented" do
|
430
|
+
Money.us_dollar( 100000).format(:sign_positive => false, :sign_before_symbol => true).should == "$1,000.00"
|
431
|
+
Money.us_dollar(-100000).format(:sign_positive => false, :sign_before_symbol => true).should == "-$1,000.00"
|
432
|
+
end
|
433
|
+
|
434
|
+
specify "(:sign_positive => false, :sign_before_symbol => false) works as documented" do
|
435
|
+
Money.us_dollar( 100000).format(:sign_positive => false, :sign_before_symbol => false).should == "$1,000.00"
|
436
|
+
Money.us_dollar( 100000).format(:sign_positive => false, :sign_before_symbol => nil).should == "$1,000.00"
|
437
|
+
Money.us_dollar(-100000).format(:sign_positive => false, :sign_before_symbol => false).should == "$-1,000.00"
|
438
|
+
Money.us_dollar(-100000).format(:sign_positive => false, :sign_before_symbol => nil).should == "$-1,000.00"
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
409
442
|
context "when the monetary value is 0" do
|
410
443
|
let(:money) { Money.us_dollar(0) }
|
411
444
|
|
data/spec/money/parsing_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe Money, "parsing" do
|
|
9
9
|
|
10
10
|
describe ".parse" do
|
11
11
|
it "is depreciated" do
|
12
|
-
Money.should_receive(:deprecate)
|
12
|
+
Money.should_receive(:deprecate).at_least(1).times
|
13
13
|
Money.parse("1.95")
|
14
14
|
end
|
15
15
|
|
@@ -32,7 +32,7 @@ describe Money, "parsing" do
|
|
32
32
|
before do
|
33
33
|
Money.assume_from_symbol = true
|
34
34
|
end
|
35
|
-
it "parses formatted inputs with the currency passed as a symbol" do
|
35
|
+
it "parses formatted inputs with the currency passed as a symbol" do
|
36
36
|
with_default_currency("EUR") do
|
37
37
|
Money.parse("$5.95").should == Money.new(595, 'USD')
|
38
38
|
end
|
data/spec/money_spec.rb
CHANGED
@@ -157,8 +157,8 @@ describe Money do
|
|
157
157
|
end
|
158
158
|
|
159
159
|
context "loading a serialized Money via YAML" do
|
160
|
-
|
161
|
-
|
160
|
+
|
161
|
+
let(:serialized) { <<YAML
|
162
162
|
!ruby/object:Money
|
163
163
|
fractional: 249.5
|
164
164
|
currency: !ruby/object:Money::Currency
|
@@ -178,12 +178,30 @@ describe Money do
|
|
178
178
|
mutex: !ruby/object:Mutex {}
|
179
179
|
last_updated: 2012-11-23 20:41:47.454438399 +02:00
|
180
180
|
YAML
|
181
|
+
}
|
182
|
+
|
183
|
+
it "uses BigDecimal when rounding" do
|
181
184
|
m = YAML::load serialized
|
182
185
|
m.should be_a(Money)
|
183
186
|
m.class.infinite_precision.should == false
|
184
187
|
m.fractional.should == 250 # 249.5 rounded up
|
185
188
|
m.fractional.should be_a(Integer)
|
186
189
|
end
|
190
|
+
|
191
|
+
context "with infinite_precision" do
|
192
|
+
before do
|
193
|
+
Money.infinite_precision = true
|
194
|
+
end
|
195
|
+
|
196
|
+
after do
|
197
|
+
Money.infinite_precision = false
|
198
|
+
end
|
199
|
+
|
200
|
+
it "is a BigDecimal" do
|
201
|
+
money = YAML::load serialized
|
202
|
+
money.fractional.should be_a BigDecimal
|
203
|
+
end
|
204
|
+
end
|
187
205
|
end
|
188
206
|
|
189
207
|
context "user changes rounding_mode" do
|
@@ -239,6 +257,10 @@ YAML
|
|
239
257
|
Money.new(100_37).amount.should == 100.37
|
240
258
|
Money.new_with_amount(100.37).amount.should == 100.37
|
241
259
|
end
|
260
|
+
|
261
|
+
it 'produces a BigDecimal' do
|
262
|
+
Money.new(1_00).amount.should be_a BigDecimal
|
263
|
+
end
|
242
264
|
end
|
243
265
|
|
244
266
|
describe "#dollars" do
|
@@ -494,4 +516,49 @@ YAML
|
|
494
516
|
end
|
495
517
|
end
|
496
518
|
end
|
519
|
+
|
520
|
+
describe "#round" do
|
521
|
+
|
522
|
+
let(:money) { Money.new(15.75, 'NZD') }
|
523
|
+
subject(:rounded) { money.round }
|
524
|
+
|
525
|
+
context "without infinite_precision" do
|
526
|
+
before do
|
527
|
+
Money.infinite_precision = false
|
528
|
+
end
|
529
|
+
|
530
|
+
it "returns self (as it is already rounded)" do
|
531
|
+
rounded = money.round
|
532
|
+
rounded.should be money
|
533
|
+
rounded.cents.should eq 16
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
context "with infinite_precision" do
|
538
|
+
before do
|
539
|
+
Money.infinite_precision = true
|
540
|
+
end
|
541
|
+
|
542
|
+
after do
|
543
|
+
Money.infinite_precision = false
|
544
|
+
end
|
545
|
+
|
546
|
+
it "returns a different money" do
|
547
|
+
rounded.should_not be money
|
548
|
+
end
|
549
|
+
|
550
|
+
it "rounds the cents" do
|
551
|
+
rounded.cents.should eq 16
|
552
|
+
end
|
553
|
+
|
554
|
+
it "maintains the currency" do
|
555
|
+
rounded.currency.should eq Money::Currency.new('NZD')
|
556
|
+
end
|
557
|
+
|
558
|
+
it "uses a provided rounding strategy" do
|
559
|
+
rounded = money.round(BigDecimal::ROUND_DOWN)
|
560
|
+
rounded.cents.should eq 15
|
561
|
+
end
|
562
|
+
end
|
563
|
+
end
|
497
564
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: money
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.0.0.
|
4
|
+
version: 6.0.0.pre3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Luetke
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2013-
|
15
|
+
date: 2013-09-04 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: i18n
|
@@ -80,18 +80,18 @@ files:
|
|
80
80
|
- config/currency_backwards_compatible.json
|
81
81
|
- config/currency_iso.json
|
82
82
|
- config/currency_non_iso.json
|
83
|
+
- lib/money.rb
|
83
84
|
- lib/money/bank/base.rb
|
84
85
|
- lib/money/bank/variable_exchange.rb
|
85
86
|
- lib/money/core_extensions.rb
|
87
|
+
- lib/money/currency.rb
|
86
88
|
- lib/money/currency/heuristics.rb
|
87
89
|
- lib/money/currency/loader.rb
|
88
|
-
- lib/money/currency.rb
|
89
90
|
- lib/money/deprecations.rb
|
91
|
+
- lib/money/money.rb
|
90
92
|
- lib/money/money/arithmetic.rb
|
91
93
|
- lib/money/money/formatting.rb
|
92
94
|
- lib/money/money/parsing.rb
|
93
|
-
- lib/money/money.rb
|
94
|
-
- lib/money.rb
|
95
95
|
- spec/bank/base_spec.rb
|
96
96
|
- spec/bank/variable_exchange_spec.rb
|
97
97
|
- spec/core_extensions_spec.rb
|
@@ -112,7 +112,16 @@ homepage: http://rubymoney.github.com/money
|
|
112
112
|
licenses:
|
113
113
|
- MIT
|
114
114
|
metadata: {}
|
115
|
-
post_install_message:
|
115
|
+
post_install_message: |2
|
116
|
+
|
117
|
+
Please note the following API changes in Money version 6
|
118
|
+
|
119
|
+
- Money#amount, Money#dollars methods now return instances of BigDecimal (rather than Float).
|
120
|
+
|
121
|
+
Please read the migration notes at https://github.com/RubyMoney/money#migration-notes
|
122
|
+
and choose the migration that best suits your application.
|
123
|
+
|
124
|
+
Test responsibly :-)
|
116
125
|
rdoc_options: []
|
117
126
|
require_paths:
|
118
127
|
- lib
|
@@ -128,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
128
137
|
version: 1.3.1
|
129
138
|
requirements: []
|
130
139
|
rubyforge_project:
|
131
|
-
rubygems_version: 2.0.
|
140
|
+
rubygems_version: 2.0.3
|
132
141
|
signing_key:
|
133
142
|
specification_version: 4
|
134
143
|
summary: Money and currency exchange support library.
|