money 6.7.1 → 6.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -1
  3. data/.travis.yml +15 -6
  4. data/AUTHORS +5 -0
  5. data/CHANGELOG.md +98 -3
  6. data/Gemfile +13 -4
  7. data/LICENSE +2 -0
  8. data/README.md +64 -44
  9. data/config/currency_backwards_compatible.json +30 -0
  10. data/config/currency_iso.json +135 -59
  11. data/config/currency_non_iso.json +66 -2
  12. data/lib/money.rb +0 -13
  13. data/lib/money/bank/variable_exchange.rb +9 -22
  14. data/lib/money/currency.rb +33 -39
  15. data/lib/money/currency/heuristics.rb +1 -144
  16. data/lib/money/currency/loader.rb +1 -1
  17. data/lib/money/locale_backend/base.rb +7 -0
  18. data/lib/money/locale_backend/errors.rb +6 -0
  19. data/lib/money/locale_backend/i18n.rb +24 -0
  20. data/lib/money/locale_backend/legacy.rb +28 -0
  21. data/lib/money/money.rb +106 -139
  22. data/lib/money/money/allocation.rb +37 -0
  23. data/lib/money/money/arithmetic.rb +31 -28
  24. data/lib/money/money/constructors.rb +1 -2
  25. data/lib/money/money/formatter.rb +397 -0
  26. data/lib/money/money/formatting_rules.rb +120 -0
  27. data/lib/money/money/locale_backend.rb +20 -0
  28. data/lib/money/rates_store/memory.rb +1 -2
  29. data/lib/money/version.rb +1 -1
  30. data/money.gemspec +10 -16
  31. data/spec/bank/variable_exchange_spec.rb +7 -3
  32. data/spec/currency/heuristics_spec.rb +2 -153
  33. data/spec/currency_spec.rb +44 -3
  34. data/spec/locale_backend/i18n_spec.rb +62 -0
  35. data/spec/locale_backend/legacy_spec.rb +74 -0
  36. data/spec/money/allocation_spec.rb +130 -0
  37. data/spec/money/arithmetic_spec.rb +184 -90
  38. data/spec/money/constructors_spec.rb +0 -12
  39. data/spec/money/formatting_spec.rb +296 -179
  40. data/spec/money/locale_backend_spec.rb +14 -0
  41. data/spec/money_spec.rb +159 -26
  42. data/spec/rates_store/memory_spec.rb +13 -2
  43. data/spec/spec_helper.rb +2 -0
  44. data/spec/support/shared_examples/money_examples.rb +14 -0
  45. metadata +32 -40
  46. data/lib/money/money/formatting.rb +0 -418
@@ -3,7 +3,9 @@ require "money/bank/variable_exchange"
3
3
  require "money/bank/single_currency"
4
4
  require "money/money/arithmetic"
5
5
  require "money/money/constructors"
6
- require "money/money/formatting"
6
+ require "money/money/formatter"
7
+ require "money/money/allocation"
8
+ require "money/money/locale_backend"
7
9
 
8
10
  # "Money is any object or record that is generally accepted as payment for
9
11
  # goods and services and repayment of debts in a given socio-economic context
@@ -17,7 +19,6 @@ require "money/money/formatting"
17
19
  class Money
18
20
  include Comparable
19
21
  include Money::Arithmetic
20
- include Money::Formatting
21
22
  extend Constructors
22
23
 
23
24
  # Raised when smallest denomination of a currency is not defined
@@ -105,9 +106,9 @@ class Money
105
106
  # @see +Money::Formatting#format+ for more details.
106
107
  #
107
108
  # @example
108
- # Money.default_formatting_rules = { :display_free => true }
109
+ # Money.default_formatting_rules = { display_free: true }
109
110
  # Money.new(0, "USD").format # => "free"
110
- # Money.new(0, "USD").format(:display_free => false) # => "$0.00"
111
+ # Money.new(0, "USD").format(display_free: false) # => "$0.00"
111
112
  #
112
113
  # @!attribute [rw] use_i18n
113
114
  # @return [Boolean] Use this to disable i18n even if it's used by other
@@ -117,10 +118,11 @@ class Money
117
118
  # @return [Boolean] Use this to enable infinite precision cents
118
119
  #
119
120
  # @!attribute [rw] conversion_precision
120
- # @return [Fixnum] Use this to specify precision for converting Rational
121
+ # @return [Integer] Use this to specify precision for converting Rational
121
122
  # to BigDecimal
122
123
  attr_accessor :default_bank, :default_formatting_rules,
123
- :use_i18n, :infinite_precision, :conversion_precision
124
+ :use_i18n, :infinite_precision, :conversion_precision,
125
+ :locale_backend
124
126
 
125
127
  # @attr_writer rounding_mode Use this to specify the rounding mode
126
128
  #
@@ -141,6 +143,18 @@ class Money
141
143
  end
142
144
  end
143
145
 
146
+ def self.locale_backend=(value)
147
+ @locale_backend = value ? LocaleBackend.find(value) : nil
148
+ end
149
+
150
+ def self.use_i18n=(value)
151
+ if value
152
+ warn '[DEPRECATION] `use_i18n` is deprecated - use `Money.locale_backend = :i18n` instead'
153
+ end
154
+
155
+ @use_i18n = value
156
+ end
157
+
144
158
  def self.setup_defaults
145
159
  # Set the default bank for creating new +Money+ objects.
146
160
  self.default_bank = Bank::VariableExchange.instance
@@ -149,7 +163,10 @@ class Money
149
163
  self.default_currency = Currency.new("USD")
150
164
 
151
165
  # Default to using i18n
152
- self.use_i18n = true
166
+ @use_i18n = true
167
+
168
+ # Default to using legacy locale backend
169
+ self.locale_backend = :legacy
153
170
 
154
171
  # Default to not using infinite precision cents
155
172
  self.infinite_precision = false
@@ -177,9 +194,9 @@ class Money
177
194
  #
178
195
  # @example
179
196
  # fee = Money.rounding_mode(BigDecimal::ROUND_HALF_UP) do
180
- # Money.new(1200) * BigDecimal.new('0.029')
197
+ # Money.new(1200) * BigDecimal('0.029')
181
198
  # end
182
- def self.rounding_mode(mode=nil)
199
+ def self.rounding_mode(mode = nil)
183
200
  if mode.nil?
184
201
  Thread.current[:money_rounding_mode] || @rounding_mode
185
202
  else
@@ -228,8 +245,9 @@ class Money
228
245
  #
229
246
  # @see #initialize
230
247
  def self.from_amount(amount, currency = default_currency, bank = default_bank)
231
- Numeric === amount or raise ArgumentError, "'amount' must be numeric"
232
- currency = Currency.wrap(currency)
248
+ raise ArgumentError, "'amount' must be numeric" unless Numeric === amount
249
+
250
+ currency = Currency.wrap(currency) || Money.default_currency
233
251
  value = amount.to_d * currency.subunit_to_unit
234
252
  value = value.round(0, rounding_mode) unless infinite_precision
235
253
  new(value, currency, bank)
@@ -271,7 +289,7 @@ class Money
271
289
  # @return [BigDecimal]
272
290
  #
273
291
  # @example
274
- # Money.new(1_00, "USD").dollars # => BigDecimal.new("1.00")
292
+ # Money.new(1_00, "USD").dollars # => BigDecimal("1.00")
275
293
  #
276
294
  # @see #amount
277
295
  # @see #to_d
@@ -286,7 +304,7 @@ class Money
286
304
  # @return [BigDecimal]
287
305
  #
288
306
  # @example
289
- # Money.new(1_00, "USD").amount # => BigDecimal.new("1.00")
307
+ # Money.new(1_00, "USD").amount # => BigDecimal("1.00")
290
308
  #
291
309
  # @see #to_d
292
310
  # @see #fractional
@@ -302,6 +320,7 @@ class Money
302
320
  # @example
303
321
  # Money.new(100, :USD).currency_as_string #=> "USD"
304
322
  def currency_as_string
323
+ warn "[DEPRECATION] `currency_as_string` is deprecated. Please use `.currency.to_s` instead."
305
324
  currency.to_s
306
325
  end
307
326
 
@@ -314,13 +333,15 @@ class Money
314
333
  # @example
315
334
  # Money.new(100).currency_as_string("CAD") #=> #<Money::Currency id: cad>
316
335
  def currency_as_string=(val)
336
+ warn "[DEPRECATION] `currency_as_string=` is deprecated - Money instances are immutable." \
337
+ " Please use `with_currency` instead."
317
338
  @currency = Currency.wrap(val)
318
339
  end
319
340
 
320
- # Returns a Fixnum hash value based on the +fractional+ and +currency+ attributes
341
+ # Returns a Integer hash value based on the +fractional+ and +currency+ attributes
321
342
  # in order to use functions like & (intersection), group_by, etc.
322
343
  #
323
- # @return [Fixnum]
344
+ # @return [Integer]
324
345
  #
325
346
  # @example
326
347
  # Money.new(100).hash #=> 908351
@@ -352,19 +373,10 @@ class Money
352
373
  # @example
353
374
  # Money.ca_dollar(100).to_s #=> "1.00"
354
375
  def to_s
355
- unit, subunit, fraction = strings_from_fractional
356
-
357
- str = if currency.decimal_places == 0
358
- if fraction == ""
359
- unit
360
- else
361
- "#{unit}#{decimal_mark}#{fraction}"
362
- end
363
- else
364
- "#{unit}#{decimal_mark}#{pad_subunit(subunit)}#{fraction}"
365
- end
366
-
367
- fractional < 0 ? "-#{str}" : str
376
+ format thousands_separator: '',
377
+ no_cents_if_whole: currency.decimal_places == 0,
378
+ symbol: false,
379
+ ignore_defaults: true
368
380
  end
369
381
 
370
382
  # Return the amount of money as a BigDecimal.
@@ -372,7 +384,7 @@ class Money
372
384
  # @return [BigDecimal]
373
385
  #
374
386
  # @example
375
- # Money.us_dollar(1_00).to_d #=> BigDecimal.new("1.00")
387
+ # Money.us_dollar(1_00).to_d #=> BigDecimal("1.00")
376
388
  def to_d
377
389
  as_d(fractional) / as_d(currency.subunit_to_unit)
378
390
  end
@@ -400,7 +412,22 @@ class Money
400
412
  to_d.to_f
401
413
  end
402
414
 
403
- # Conversation to +self+.
415
+ # Returns a new Money instance in a given currency leaving the amount intact
416
+ # and not performing currency conversion.
417
+ #
418
+ # @param [Currency, String, Symbol] new_currency Currency of the new object.
419
+ #
420
+ # @return [self]
421
+ def with_currency(new_currency)
422
+ new_currency = Currency.wrap(new_currency)
423
+ if !new_currency || currency == new_currency
424
+ self
425
+ else
426
+ self.class.new(fractional, new_currency, bank)
427
+ end
428
+ end
429
+
430
+ # Conversion to +self+.
404
431
  #
405
432
  # @return [self]
406
433
  def to_money(given_currency = nil)
@@ -473,52 +500,27 @@ class Money
473
500
  exchange_to("EUR")
474
501
  end
475
502
 
476
- # Allocates money between different parties without losing pennies.
477
- # After the mathematical split has been performed, leftover pennies will
478
- # be distributed round-robin amongst the parties. This means that parties
479
- # listed first will likely receive more pennies than ones that are listed later
503
+ # Splits a given amount in parts without loosing pennies. The left-over pennies will be
504
+ # distributed round-robin amongst the parties. This means that parties listed first will likely
505
+ # receive more pennies than ones that are listed later.
480
506
  #
481
- # @param [Array<Numeric>] splits [0.50, 0.25, 0.25] to give 50% of the cash to party1, 25% to party2, and 25% to party3.
507
+ # @param [Array<Numeric>, Numeric] pass [2, 1, 1] to give twice as much to party1 as party2 or
508
+ # party3 which results in 50% of the cash to party1, 25% to party2, and 25% to party3. Passing a
509
+ # number instead of an array will split the amount evenly (without loosing pennies when rounding).
482
510
  #
483
511
  # @return [Array<Money>]
484
512
  #
485
513
  # @example
486
- # Money.new(5, "USD").allocate([0.3, 0.7]) #=> [Money.new(2), Money.new(3)]
487
- # Money.new(100, "USD").allocate([0.33, 0.33, 0.33]) #=> [Money.new(34), Money.new(33), Money.new(33)]
488
- #
489
- def allocate(splits)
490
- allocations = allocations_from_splits(splits)
491
-
492
- if (allocations - BigDecimal("1")) > Float::EPSILON
493
- raise ArgumentError, "splits add to more then 100%"
494
- end
495
-
496
- amounts, left_over = amounts_from_splits(allocations, splits)
497
-
498
- unless self.class.infinite_precision
499
- left_over.to_i.times { |i| amounts[i % amounts.length] += 1 }
500
- end
501
-
502
- amounts.collect { |fractional| self.class.new(fractional, currency) }
503
- end
504
-
505
- # Split money amongst parties evenly without losing pennies.
506
- #
507
- # @param [Numeric] num number of parties.
514
+ # Money.new(5, "USD").allocate([3, 7]) #=> [Money.new(2), Money.new(3)]
515
+ # Money.new(100, "USD").allocate([1, 1, 1]) #=> [Money.new(34), Money.new(33), Money.new(33)]
516
+ # Money.new(100, "USD").allocate(2) #=> [Money.new(50), Money.new(50)]
517
+ # Money.new(100, "USD").allocate(3) #=> [Money.new(34), Money.new(33), Money.new(33)]
508
518
  #
509
- # @return [Array<Money>]
510
- #
511
- # @example
512
- # Money.new(100, "USD").split(3) #=> [Money.new(34), Money.new(33), Money.new(33)]
513
- def split(num)
514
- raise ArgumentError, "need at least one party" if num < 1
515
-
516
- if self.class.infinite_precision
517
- split_infinite(num)
518
- else
519
- split_flat(num)
520
- end
519
+ def allocate(parts)
520
+ amounts = Money::Allocation.generate(fractional, parts, !Money.infinite_precision)
521
+ amounts.map { |amount| self.class.new(amount, currency) }
521
522
  end
523
+ alias_method :split, :allocate
522
524
 
523
525
  # Round the monetary amount to smallest unit of coinage.
524
526
  #
@@ -535,85 +537,46 @@ class Money
535
537
  # @see
536
538
  # Money.infinite_precision
537
539
  #
538
- def round(rounding_mode = self.class.rounding_mode)
539
- if self.class.infinite_precision
540
- self.class.new(fractional.round(0, rounding_mode), self.currency)
541
- else
542
- self
543
- end
544
- end
545
-
546
- private
547
-
548
- def as_d(num)
549
- if num.respond_to?(:to_d)
550
- num.is_a?(Rational) ? num.to_d(self.class.conversion_precision) : num.to_d
551
- else
552
- BigDecimal.new(num.to_s)
553
- end
540
+ def round(rounding_mode = self.class.rounding_mode, rounding_precision = 0)
541
+ rounded_amount = as_d(@fractional).round(rounding_precision, rounding_mode)
542
+ self.class.new(rounded_amount, currency, bank)
554
543
  end
555
544
 
556
- def strings_from_fractional
557
- unit, subunit = fractional().abs.divmod(currency.subunit_to_unit)
558
-
559
- if self.class.infinite_precision
560
- strings_for_infinite_precision(unit, subunit)
561
- else
562
- strings_for_base_precision(unit, subunit)
563
- end
564
- end
565
-
566
- def strings_for_infinite_precision(unit, subunit)
567
- subunit, fraction = subunit.divmod(BigDecimal("1"))
568
- fraction = fraction.to_s("F")[2..-1] # want fractional part "0.xxx"
569
- fraction = "" if fraction =~ /^0+$/
570
-
571
- [unit.to_i.to_s, subunit.to_i.to_s, fraction]
572
- end
573
-
574
- def strings_for_base_precision(unit, subunit)
575
- [unit.to_s, subunit.to_s, ""]
576
- end
577
-
578
- def pad_subunit(subunit)
579
- cnt = currency.decimal_places
580
- padding = "0" * cnt
581
- "#{padding}#{subunit}"[-1 * cnt, cnt]
582
- end
583
-
584
- def allocations_from_splits(splits)
585
- splits.inject(0) { |sum, n| sum + as_d(n) }
545
+ # Creates a formatted price string according to several rules.
546
+ #
547
+ # @param [Hash] See Money::Formatter for the list of formatting options
548
+ #
549
+ # @return [String]
550
+ #
551
+ def format(*rules)
552
+ Money::Formatter.new(self, *rules).to_s
586
553
  end
587
554
 
588
- def amounts_from_splits(allocations, splits)
589
- left_over = fractional
590
-
591
- amounts = splits.map do |ratio|
592
- if self.class.infinite_precision
593
- fractional * ratio
594
- else
595
- (fractional * ratio / allocations).floor.tap do |frac|
596
- left_over -= frac
597
- end
598
- end
599
- end
600
-
601
- [amounts, left_over]
555
+ # Returns a thousands separator according to the locale
556
+ #
557
+ # @return [String]
558
+ #
559
+ def thousands_separator
560
+ (locale_backend && locale_backend.lookup(:thousands_separator, currency)) ||
561
+ Money::Formatter::DEFAULTS[:thousands_separator]
602
562
  end
603
563
 
604
- def split_infinite(num)
605
- amt = div(as_d(num))
606
- 1.upto(num).map{amt}
564
+ # Returns a decimal mark according to the locale
565
+ #
566
+ # @return [String]
567
+ #
568
+ def decimal_mark
569
+ (locale_backend && locale_backend.lookup(:decimal_mark, currency)) ||
570
+ Money::Formatter::DEFAULTS[:decimal_mark]
607
571
  end
608
572
 
609
- def split_flat(num)
610
- low = self.class.new(fractional / num, currency)
611
- high = self.class.new(low.fractional + 1, currency)
612
-
613
- remainder = fractional % num
573
+ private
614
574
 
615
- Array.new(num).each_with_index.map do |_, index|
616
- index < remainder ? high : low
575
+ def as_d(num)
576
+ if num.respond_to?(:to_d)
577
+ num.is_a?(Rational) ? num.to_d(self.class.conversion_precision) : num.to_d
578
+ else
579
+ BigDecimal(num.to_s.empty? ? 0 : num.to_s)
617
580
  end
618
581
  end
619
582
 
@@ -624,4 +587,8 @@ class Money
624
587
  value.round(0, self.class.rounding_mode).to_i
625
588
  end
626
589
  end
590
+
591
+ def locale_backend
592
+ self.class.locale_backend
593
+ end
627
594
  end
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+
3
+ class Money
4
+ class Allocation
5
+ # Splits a given amount in parts without loosing pennies.
6
+ # The left-over pennies will be distributed round-robin amongst the parties. This means that
7
+ # parties listed first will likely receive more pennies than ones that are listed later.
8
+ #
9
+ # The results should always add up to the original amount.
10
+ #
11
+ # The parts can be specified as:
12
+ # Numeric — performs the split between a given number of parties evenely
13
+ # Array<Numeric> — allocates the amounts proportionally to the given array
14
+ #
15
+ def self.generate(amount, parts, whole_amounts = true)
16
+ parts = parts.is_a?(Numeric) ? Array.new(parts, 1) : parts.dup
17
+
18
+ raise ArgumentError, 'need at least one party' if parts.empty?
19
+
20
+ result = []
21
+ remaining_amount = amount
22
+
23
+ until parts.empty? do
24
+ parts_sum = parts.inject(0, :+)
25
+ part = parts.pop
26
+
27
+ current_split = remaining_amount * part / parts_sum
28
+ current_split = current_split.truncate if whole_amounts
29
+
30
+ result.unshift current_split
31
+ remaining_amount -= current_split
32
+ end
33
+
34
+ result
35
+ end
36
+ end
37
+ end
@@ -16,7 +16,7 @@ class Money
16
16
  # @example
17
17
  # - Money.new(100) #=> #<Money @fractional=-100>
18
18
  def -@
19
- self.class.new(-fractional, currency)
19
+ self.class.new(-fractional, currency, bank)
20
20
  end
21
21
 
22
22
  # Checks whether two Money objects have the same currency and the same
@@ -48,16 +48,17 @@ class Money
48
48
  #
49
49
  # @param [Money] other_money Value to compare with.
50
50
  #
51
- # @return [Fixnum]
51
+ # @return [Integer]
52
52
  #
53
53
  # @raise [TypeError] when other object is not Money
54
54
  #
55
55
  def <=>(other)
56
- if other.respond_to?(:zero?) && other.zero?
56
+ unless other.is_a?(Money)
57
+ return unless other.respond_to?(:zero?) && other.zero?
57
58
  return other.is_a?(CoercedNumeric) ? 0 <=> fractional : fractional <=> 0
58
59
  end
59
- return unless other.is_a?(Money)
60
- other = other.exchange_to(currency) if nonzero? && currency != other.currency
60
+ return 0 if zero? && other.zero?
61
+ other = other.exchange_to(currency)
61
62
  fractional <=> other.fractional
62
63
  rescue Money::Bank::UnknownRate
63
64
  end
@@ -97,6 +98,7 @@ class Money
97
98
  fractional < 0
98
99
  end
99
100
 
101
+ # @method +(other)
100
102
  # Returns a new Money object containing the sum of the two operands' monetary
101
103
  # values. If +other_money+ has a different currency then its monetary value
102
104
  # is automatically exchanged to this object's currency using +exchange_to+.
@@ -107,13 +109,8 @@ class Money
107
109
  #
108
110
  # @example
109
111
  # Money.new(100) + Money.new(100) #=> #<Money @fractional=200>
110
- def +(other_money)
111
- return self if other_money.zero?
112
- raise TypeError unless other_money.is_a?(Money)
113
- other_money = other_money.exchange_to(currency)
114
- self.class.new(fractional + other_money.fractional, currency)
115
- end
116
-
112
+ #
113
+ # @method -(other)
117
114
  # Returns a new Money object containing the difference between the two
118
115
  # operands' monetary values. If +other_money+ has a different currency then
119
116
  # its monetary value is automatically exchanged to this object's currency
@@ -125,11 +122,17 @@ class Money
125
122
  #
126
123
  # @example
127
124
  # Money.new(100) - Money.new(99) #=> #<Money @fractional=1>
128
- def -(other_money)
129
- return self if other_money.zero?
130
- raise TypeError unless other_money.is_a?(Money)
131
- other_money = other_money.exchange_to(currency)
132
- self.class.new(fractional - other_money.fractional, currency)
125
+ [:+, :-].each do |op|
126
+ define_method(op) do |other|
127
+ unless other.is_a?(Money)
128
+ if other.zero?
129
+ return other.is_a?(CoercedNumeric) ? Money.empty(currency).public_send(op, self) : self
130
+ end
131
+ raise TypeError
132
+ end
133
+ other = other.exchange_to(currency)
134
+ self.class.new(fractional.public_send(op, other.fractional), currency, bank)
135
+ end
133
136
  end
134
137
 
135
138
  # Multiplies the monetary value with the given number and returns a new
@@ -149,7 +152,7 @@ class Money
149
152
  def *(value)
150
153
  value = value.value if value.is_a?(CoercedNumeric)
151
154
  if value.is_a? Numeric
152
- self.class.new(fractional * value, currency)
155
+ self.class.new(fractional * value, currency, bank)
153
156
  else
154
157
  raise TypeError, "Can't multiply a #{self.class.name} by a #{value.class.name}'s value"
155
158
  end
@@ -175,7 +178,7 @@ class Money
175
178
  fractional / as_d(value.exchange_to(currency).fractional).to_f
176
179
  else
177
180
  raise TypeError, 'Can not divide by Money' if value.is_a?(CoercedNumeric)
178
- self.class.new(fractional / as_d(value), currency)
181
+ self.class.new(fractional / as_d(value), currency, bank)
179
182
  end
180
183
  end
181
184
 
@@ -195,9 +198,9 @@ class Money
195
198
  # Divide money by money or fixnum and return array containing quotient and
196
199
  # modulus.
197
200
  #
198
- # @param [Money, Fixnum] val Number to divmod by.
201
+ # @param [Money, Integer] val Number to divmod by.
199
202
  #
200
- # @return [Array<Money,Money>,Array<Fixnum,Money>]
203
+ # @return [Array<Money,Money>,Array<Integer,Money>]
201
204
  #
202
205
  # @example
203
206
  # Money.new(100).divmod(9) #=> [#<Money @fractional=11>, #<Money @fractional=1>]
@@ -213,19 +216,19 @@ class Money
213
216
  def divmod_money(val)
214
217
  cents = val.exchange_to(currency).cents
215
218
  quotient, remainder = fractional.divmod(cents)
216
- [quotient, self.class.new(remainder, currency)]
219
+ [quotient, self.class.new(remainder, currency, bank)]
217
220
  end
218
221
  private :divmod_money
219
222
 
220
223
  def divmod_other(val)
221
224
  quotient, remainder = fractional.divmod(as_d(val))
222
- [self.class.new(quotient, currency), self.class.new(remainder, currency)]
225
+ [self.class.new(quotient, currency, bank), self.class.new(remainder, currency, bank)]
223
226
  end
224
227
  private :divmod_other
225
228
 
226
229
  # Equivalent to +self.divmod(val)[1]+
227
230
  #
228
- # @param [Money, Fixnum] val Number take modulo with.
231
+ # @param [Money, Integer] val Number take modulo with.
229
232
  #
230
233
  # @return [Money]
231
234
  #
@@ -238,7 +241,7 @@ class Money
238
241
 
239
242
  # Synonym for +#modulo+.
240
243
  #
241
- # @param [Money, Fixnum] val Number take modulo with.
244
+ # @param [Money, Integer] val Number take modulo with.
242
245
  #
243
246
  # @return [Money]
244
247
  #
@@ -249,7 +252,7 @@ class Money
249
252
 
250
253
  # If different signs +self.modulo(val) - val+ otherwise +self.modulo(val)+
251
254
  #
252
- # @param [Money, Fixnum] val Number to rake remainder with.
255
+ # @param [Money, Integer] val Number to rake remainder with.
253
256
  #
254
257
  # @return [Money]
255
258
  #
@@ -263,7 +266,7 @@ class Money
263
266
  if (fractional < 0 && val < 0) || (fractional > 0 && val > 0)
264
267
  self.modulo(val)
265
268
  else
266
- self.modulo(val) - (val.is_a?(Money) ? val : self.class.new(val, currency))
269
+ self.modulo(val) - (val.is_a?(Money) ? val : self.class.new(val, currency, bank))
267
270
  end
268
271
  end
269
272
 
@@ -274,7 +277,7 @@ class Money
274
277
  # @example
275
278
  # Money.new(-100).abs #=> #<Money @fractional=100>
276
279
  def abs
277
- self.class.new(fractional.abs, currency)
280
+ self.class.new(fractional.abs, currency, bank)
278
281
  end
279
282
 
280
283
  # Test if the money amount is zero.