money 6.0.0.pre2 → 6.0.0.pre3
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 +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
|
[](http://badge.fury.io/rb/money) [](https://travis-ci.org/RubyMoney/money) [](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.
|