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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: db3de84c7fca4fad50f28617c05aa96b0a8cd2f9
4
- data.tar.gz: 3a22bb6c242e6b96660f78add455217a5eac3e5d
3
+ metadata.gz: b9dae4831f4901cf906ae3d6f155c9bac6e3f67f
4
+ data.tar.gz: 43718a7d7edfce6329053cd90a7b61ec2d4d3a78
5
5
  SHA512:
6
- metadata.gz: c55f42b4d76f62ba787b54ef929d202f1edd873d9abc7139fc1cb8e5276f59263d293f4b1c316e35cf814493c211598adee7812b83d23f60e51d276d7bbe6919
7
- data.tar.gz: c6b9250d167858e374ab2ae18da527aa4d3c06017a60cb8574190da4afca629020bdf18d4e0005abd2fd48b80dbced701b61e16bce81dbf78aee87b83933437a
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.
@@ -1731,7 +1731,7 @@
1731
1731
  "symbol_first": false,
1732
1732
  "html_entity": "",
1733
1733
  "decimal_mark": ",",
1734
- "thousands_separator": ".",
1734
+ "thousands_separator": " ",
1735
1735
  "iso_numeric": "752"
1736
1736
  },
1737
1737
  "sgd": {
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
- @fractional
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
- # If the Money object is created from a serialized YAML string,
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 = if fractional.is_a?(Rational)
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 [Float]
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 #to_f
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 [Float]
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 #to_f
285
+ # @see #to_d
281
286
  # @see #fractional
282
287
  #
283
288
  def amount
284
- to_f
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
- BigDecimal.new(fractional.to_s) / BigDecimal.new(currency.subunit_to_unit.to_s)
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
- # decimals.
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(BigDecimal("0")) do |sum, n|
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 = self.div(BigDecimal(num.to_s))
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, self.currency)
524
- high = Money.new(low.fractional + 1, self.currency)
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 && self.currency == other_money.currency
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
- if currency == other_money.currency
97
- Money.new(fractional + other_money.fractional, other_money.currency)
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
- if currency == other_money.currency
116
- Money.new(fractional - other_money.fractional, other_money.currency)
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 Money instance.
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?(Money)
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
- if currency == value.currency
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 = self.fractional
197
- b = self.currency == val.currency ? val.fractional : val.exchange_to(self.currency).cents
186
+ a = fractional
187
+ b = val.exchange_to(currency).cents
198
188
  q, m = a.divmod(b)
199
- return [q, Money.new(m, self.currency)]
189
+ return [q, Money.new(m, currency)]
200
190
  else
201
191
  if self.class.infinite_precision
202
- q, m = self.fractional.divmod(BigDecimal(val.to_s))
203
- return [Money.new(q, self.currency), Money.new(m, self.currency)]
192
+ q, m = fractional.divmod(as_d(val))
193
+ return [Money.new(q, currency), Money.new(m, currency)]
204
194
  else
205
- return [self.div(val), Money.new(self.fractional.modulo(val), self.currency)]
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
- self.divmod(val)[1]
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
- self.modulo(val)
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(self.fractional.abs, self.currency)
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
- formatted = rules[:no_cents] ? "#{self.to_s.to_i}" : self.to_s
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
- sign = ""
237
- if rules[:sign_before_symbol] == true && self.negative?
238
- formatted.tr!("-", "")
239
- sign = "-"
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
- "#{sign}#{symbol_value}#{symbol_space}#{formatted}"
264
+ "#{sign_before}#{symbol_value}#{symbol_space}#{sign}#{formatted}"
248
265
  else
249
266
  symbol_space = rules[:symbol_after_without_space] ? "" : " "
250
- "#{sign}#{formatted}#{symbol_space}#{symbol_value}"
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.pre2"
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(-4, :USD)},
269
- {:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-4, :USD)},
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(-4, :USD)},
330
- {:a => Money.new(-13, :USD), :b => 4, :c => Money.new(-4, :USD)},
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(-4, :USD), Money.new(-3, :USD)]},
391
- {:a => Money.new(-13, :USD), :b => 4, :c => [Money.new(-4, :USD), Money.new( 3, :USD)]},
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").format.should == "1,000円"
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.000,00 kr"
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
 
@@ -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
- it "uses BigDecimal when rounding" do
161
- serialized = <<YAML
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.pre2
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-07-27 00:00:00.000000000 Z
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.2
140
+ rubygems_version: 2.0.3
132
141
  signing_key:
133
142
  specification_version: 4
134
143
  summary: Money and currency exchange support library.