Class: Money

Inherits:
Object
  • Object
show all
Includes:
Comparable, Arithmetic, Formatting
Defined in:
lib/money/money.rb,
lib/money/version.rb,
lib/money/currency.rb,
lib/money/bank/base.rb,
lib/money/currency/loader.rb,
lib/money/money/arithmetic.rb,
lib/money/money/formatting.rb,
lib/money/currency/heuristics.rb,
lib/money/bank/single_currency.rb,
lib/money/bank/variable_exchange.rb

Overview

“Money is any object or record that is generally accepted as payment for goods and services and repayment of debts in a given socio-economic context or country.” -Wikipedia

An instance of Money represents an amount of a specific currency.

Money is a value object and should be treated as immutable.

Defined Under Namespace

Modules: Arithmetic, Bank, Formatting Classes: Currency, UndefinedSmallestDenomination

Constant Summary

VERSION =
"6.4.0"

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Arithmetic

#%, #*, #+, #-, #-@, #/, #<=>, #==, #abs, #coerce, #div, #divmod, #eql?, #modulo, #negative?, #nonzero?, #positive?, #remainder, #zero?

Methods included from Formatting

define_i18n_method, #format, included

Constructor Details

#initialize(obj, currency = Money.default_currency, bank = Money.default_bank) ⇒ Money

Creates a new Money object of value given in the fractional unit of the given currency.

Alternatively you can use the convenience methods like ca_dollar and us_dollar.

Examples:

Money.new(100)        #=> #<Money @fractional=100 @currency="USD">
Money.new(100, "USD") #=> #<Money @fractional=100 @currency="USD">
Money.new(100, "EUR") #=> #<Money @fractional=100 @currency="EUR">

Parameters:

  • fractional (Numeric)

    The value given in the fractional unit.

  • currency (Currency, String, Symbol) (defaults to: Money.default_currency)

    The currency format.

  • bank (Money::Bank::*) (defaults to: Money.default_bank)

    The exchange bank to use.



276
277
278
279
280
281
# File 'lib/money/money.rb', line 276

def initialize(obj, currency = Money.default_currency, bank = Money.default_bank)
  @fractional = obj.respond_to?(:fractional) ? obj.fractional : as_d(obj)
  @currency   = obj.respond_to?(:currency) ? obj.currency : Currency.wrap(currency)
  @currency ||= Money.default_currency
  @bank       = obj.respond_to?(:bank) ? obj.bank : bank
end

Class Attribute Details

.conversion_precisionObject

associated to a bank object, which is responsible for currency exchange. This property allows you to specify the default bank object. The default value for this property is an instance of Bank::VariableExchange. It allows one to specify custom exchange rates.

which is used when Money.new is called without an explicit currency argument. The default value is Currency.new(“USD”). The value must be a valid Money::Currency instance.

hash of rules for everytime Money#format is called. Rules provided on method call will be merged with the default ones. To overwrite a rule, just provide the intended value while calling format.

it's used by other objects in your app.

infinite precision cents

precision for converting Rational to BigDecimal

Examples:

Money.default_formatting_rules = { :display_free => true }
Money.new(0, "USD").format                          # => "free"
Money.new(0, "USD").format(:display_free => false)  # => "$0.00"

See Also:

  • for more details.


115
116
117
# File 'lib/money/money.rb', line 115

def conversion_precision
  @conversion_precision
end

.default_bankObject

associated to a bank object, which is responsible for currency exchange. This property allows you to specify the default bank object. The default value for this property is an instance of Bank::VariableExchange. It allows one to specify custom exchange rates.

which is used when Money.new is called without an explicit currency argument. The default value is Currency.new(“USD”). The value must be a valid Money::Currency instance.

hash of rules for everytime Money#format is called. Rules provided on method call will be merged with the default ones. To overwrite a rule, just provide the intended value while calling format.

it's used by other objects in your app.

infinite precision cents

precision for converting Rational to BigDecimal

Examples:

Money.default_formatting_rules = { :display_free => true }
Money.new(0, "USD").format                          # => "free"
Money.new(0, "USD").format(:display_free => false)  # => "$0.00"

See Also:

  • for more details.


115
116
117
# File 'lib/money/money.rb', line 115

def default_bank
  @default_bank
end

.default_currencyObject

associated to a bank object, which is responsible for currency exchange. This property allows you to specify the default bank object. The default value for this property is an instance of Bank::VariableExchange. It allows one to specify custom exchange rates.

which is used when Money.new is called without an explicit currency argument. The default value is Currency.new(“USD”). The value must be a valid Money::Currency instance.

hash of rules for everytime Money#format is called. Rules provided on method call will be merged with the default ones. To overwrite a rule, just provide the intended value while calling format.

it's used by other objects in your app.

infinite precision cents

precision for converting Rational to BigDecimal

Examples:

Money.default_formatting_rules = { :display_free => true }
Money.new(0, "USD").format                          # => "free"
Money.new(0, "USD").format(:display_free => false)  # => "$0.00"

See Also:

  • for more details.


115
116
117
# File 'lib/money/money.rb', line 115

def default_currency
  @default_currency
end

.default_formatting_rulesObject

associated to a bank object, which is responsible for currency exchange. This property allows you to specify the default bank object. The default value for this property is an instance of Bank::VariableExchange. It allows one to specify custom exchange rates.

which is used when Money.new is called without an explicit currency argument. The default value is Currency.new(“USD”). The value must be a valid Money::Currency instance.

hash of rules for everytime Money#format is called. Rules provided on method call will be merged with the default ones. To overwrite a rule, just provide the intended value while calling format.

it's used by other objects in your app.

infinite precision cents

precision for converting Rational to BigDecimal

Examples:

Money.default_formatting_rules = { :display_free => true }
Money.new(0, "USD").format                          # => "free"
Money.new(0, "USD").format(:display_free => false)  # => "$0.00"

See Also:

  • for more details.


115
116
117
# File 'lib/money/money.rb', line 115

def default_formatting_rules
  @default_formatting_rules
end

.infinite_precisionObject

associated to a bank object, which is responsible for currency exchange. This property allows you to specify the default bank object. The default value for this property is an instance of Bank::VariableExchange. It allows one to specify custom exchange rates.

which is used when Money.new is called without an explicit currency argument. The default value is Currency.new(“USD”). The value must be a valid Money::Currency instance.

hash of rules for everytime Money#format is called. Rules provided on method call will be merged with the default ones. To overwrite a rule, just provide the intended value while calling format.

it's used by other objects in your app.

infinite precision cents

precision for converting Rational to BigDecimal

Examples:

Money.default_formatting_rules = { :display_free => true }
Money.new(0, "USD").format                          # => "free"
Money.new(0, "USD").format(:display_free => false)  # => "$0.00"

See Also:

  • for more details.


115
116
117
# File 'lib/money/money.rb', line 115

def infinite_precision
  @infinite_precision
end

.rounding_mode(mode = nil) ⇒ BigDecimal::ROUND_MODE, Yield

Use this to return the rounding mode. You may also pass a rounding mode and a block to temporatly change it. It will then return the results of the block instead.

Examples:

fee = Money.rounding_mode(BigDecimal::ROUND_HALF_UP) do
  Money.new(1200) * BigDecimal.new('0.029')
end

Parameters:

  • optional (BigDecimal::ROUND_MODE)

Returns:

  • (BigDecimal::ROUND_MODE, Yield)

    rounding mode or block results



182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/money/money.rb', line 182

def self.rounding_mode(mode=nil)
  if mode.nil?
    Thread.current[:money_rounding_mode] || @rounding_mode
  else
    begin
      Thread.current[:money_rounding_mode] = mode
      yield
    ensure
      Thread.current[:money_rounding_mode] = nil
    end
  end
end

.use_i18nObject

associated to a bank object, which is responsible for currency exchange. This property allows you to specify the default bank object. The default value for this property is an instance of Bank::VariableExchange. It allows one to specify custom exchange rates.

which is used when Money.new is called without an explicit currency argument. The default value is Currency.new(“USD”). The value must be a valid Money::Currency instance.

hash of rules for everytime Money#format is called. Rules provided on method call will be merged with the default ones. To overwrite a rule, just provide the intended value while calling format.

it's used by other objects in your app.

infinite precision cents

precision for converting Rational to BigDecimal

Examples:

Money.default_formatting_rules = { :display_free => true }
Money.new(0, "USD").format                          # => "free"
Money.new(0, "USD").format(:display_free => false)  # => "$0.00"

See Also:

  • for more details.


115
116
117
# File 'lib/money/money.rb', line 115

def use_i18n
  @use_i18n
end

Instance Attribute Details

#bankObject (readonly)

perform currency exchanges with.



80
81
82
# File 'lib/money/money.rb', line 80

def bank
  @bank
end

#currencyObject (readonly)

perform currency exchanges with.



80
81
82
# File 'lib/money/money.rb', line 80

def currency
  @currency
end

Class Method Details

.add_rate(from_currency, to_currency, rate) ⇒ Numeric

Adds a new exchange rate to the default bank and return the rate.

Examples:

Money.add_rate("USD", "CAD", 1.25) #=> 1.25

Parameters:

  • from_currency (Currency, String, Symbol)

    Currency to exchange from.

  • to_currency (Currency, String, Symbol)

    Currency to exchange to.

  • rate (Numeric)

    Rate to exchange with.

Returns:

  • (Numeric)


249
250
251
# File 'lib/money/money.rb', line 249

def self.add_rate(from_currency, to_currency, rate)
  Money.default_bank.add_rate(from_currency, to_currency, rate)
end

.ca_dollar(cents) ⇒ Money

Creates a new Money object of the given value, using the Canadian dollar currency.

Examples:

n = Money.ca_dollar(100)
n.cents    #=> 100
n.currency #=> #<Money::Currency id: cad>

Parameters:

  • cents (Integer)

    The cents value.

Returns:



206
207
208
# File 'lib/money/money.rb', line 206

def self.ca_dollar(cents)
  Money.new(cents, "CAD")
end

.disallow_currency_conversion!Object

Sets the default bank to be a SingleCurrency bank that raises on currency exchange. Useful when apps operate in a single currency at a time.



255
256
257
# File 'lib/money/money.rb', line 255

def self.disallow_currency_conversion!
  self.default_bank = Bank::SingleCurrency.instance
end

.empty(currency = default_currency) ⇒ Money Also known as: zero

Create a new money object with value 0.

Examples:

Money.empty #=> #<Money @fractional=0>

Parameters:

  • currency (Currency, String, Symbol) (defaults to: default_currency)

    The currency to use.

Returns:



129
130
131
132
# File 'lib/money/money.rb', line 129

def empty(currency = default_currency)
  @empty ||= {}
  @empty[currency] ||= Money.new(0, currency).freeze
end

.euro(cents) ⇒ Money

Creates a new Money object of the given value, using the Euro currency.

Examples:

n = Money.euro(100)
n.cents    #=> 100
n.currency #=> #<Money::Currency id: eur>

Parameters:

  • cents (Integer)

    The cents value.

Returns:



235
236
237
# File 'lib/money/money.rb', line 235

def self.euro(cents)
  Money.new(cents, "EUR")
end

.inherited(base) ⇒ Object



164
165
166
# File 'lib/money/money.rb', line 164

def self.inherited(base)
  base.setup_defaults
end

.setup_defaultsObject



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/money/money.rb', line 144

def self.setup_defaults
  # Set the default bank for creating new +Money+ objects.
  self.default_bank = Bank::VariableExchange.instance

  # Set the default currency for creating new +Money+ object.
  self.default_currency = Currency.new("USD")

  # Default to using i18n
  self.use_i18n = true

  # Default to not using infinite precision cents
  self.infinite_precision = false

  # Default to bankers rounding
  self.rounding_mode = BigDecimal::ROUND_HALF_EVEN

  # Default the conversion of Rationals precision to 16
  self.conversion_precision = 16
end

.us_dollar(cents) ⇒ Money

Creates a new Money object of the given value, using the American dollar currency.

Examples:

n = Money.us_dollar(100)
n.cents    #=> 100
n.currency #=> #<Money::Currency id: usd>

Parameters:

  • cents (Integer)

    The cents value.

Returns:



221
222
223
# File 'lib/money/money.rb', line 221

def self.us_dollar(cents)
  Money.new(cents, "USD")
end

Instance Method Details

#allocate(splits) ⇒ Array<Money>

Allocates money between different parties without losing pennies. After the mathmatically split has been performed, left over pennies will be distributed round-robin amongst the parties. This means that parties listed first will likely recieve more pennies then ones that are listed later

Examples:

Money.new(5,   "USD").allocate([0.3, 0.7])         #=> [Money.new(2), Money.new(3)]
Money.new(100, "USD").allocate([0.33, 0.33, 0.33]) #=> [Money.new(34), Money.new(33), Money.new(33)]

Parameters:

  • splits (Array<Numeric>)
    0.50, 0.25, 0.25

    to give 50% of the cash to party1, 25% to party2, and 25% to party3.

Returns:



507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
# File 'lib/money/money.rb', line 507

def allocate(splits)
  allocations = allocations_from_splits(splits)

  if (allocations - BigDecimal("1")) > Float::EPSILON
    raise ArgumentError, "splits add to more then 100%"
  end

  amounts, left_over = amounts_from_splits(allocations, splits)

  unless self.class.infinite_precision
    left_over.to_i.times { |i| amounts[i % amounts.length] += 1 }
  end

  amounts.collect { |fractional| Money.new(fractional, currency) }
end

#amountBigDecimal

Returns the numerical value of the money

Examples:

Money.new(1_00, "USD").amount    # => BigDecimal.new("1.00")

Returns:

  • (BigDecimal)

See Also:



312
313
314
# File 'lib/money/money.rb', line 312

def amount
  to_d
end

#as_ca_dollarMoney

Receive a money object with the same amount as the current Money object in canadian dollar.

Examples:

n = Money.new(100, "USD").as_ca_dollar
n.currency #=> #<Money::Currency id: cad>

Returns:



478
479
480
# File 'lib/money/money.rb', line 478

def as_ca_dollar
  exchange_to("CAD")
end

#as_euroMoney

Receive a money object with the same amount as the current Money object in euro.

Examples:

n = Money.new(100, "USD").as_euro
n.currency #=> #<Money::Currency id: eur>

Returns:



490
491
492
# File 'lib/money/money.rb', line 490

def as_euro
  exchange_to("EUR")
end

#as_us_dollarMoney

Receive a money object with the same amount as the current Money object in american dollars.

Examples:

n = Money.new(100, "CAD").as_us_dollar
n.currency #=> #<Money::Currency id: usd>

Returns:



466
467
468
# File 'lib/money/money.rb', line 466

def as_us_dollar
  exchange_to("USD")
end

#centsInteger, BigDecimal

Convenience method for fractional part of the amount. Synonym of #fractional

Returns:

  • (Integer)

    when infinite_precision is false

  • (BigDecimal)

    when infinite_precision is true

See Also:



28
29
30
# File 'lib/money/money.rb', line 28

def cents
  fractional
end

#currency_as_stringString

Return string representation of currency object

Examples:

Money.new(100, :USD).currency_as_string #=> "USD"

Returns:

  • (String)


322
323
324
# File 'lib/money/money.rb', line 322

def currency_as_string
  currency.to_s
end

#currency_as_string=(val) ⇒ Money::Currency

Set currency object using a string

Examples:

Money.new(100).currency_as_string("CAD") #=> #<Money::Currency id: cad>

Parameters:

  • val (String)

    The currency string.

Returns:



334
335
336
# File 'lib/money/money.rb', line 334

def currency_as_string=(val)
  @currency = Currency.wrap(val)
end

#default_formatting_rulesObject



315
316
317
# File 'lib/money/money/formatting.rb', line 315

def default_formatting_rules
  self.class.default_formatting_rules || {}
end

#dollarsBigDecimal

Assuming using a currency using dollars: Returns the value of the money in dollars, instead of in the fractional unit cents.

Synonym of #amount

Examples:

Money.new(1_00, "USD").dollars   # => BigDecimal.new("1.00")

Returns:

  • (BigDecimal)

See Also:



298
299
300
# File 'lib/money/money.rb', line 298

def dollars
  amount
end

#exchange_to(other_currency) {|n| ... } ⇒ Money

Receive the amount of this money object in another Currency.

Examples:

Money.new(2000, "USD").exchange_to("EUR")
Money.new(2000, "USD").exchange_to("EUR") {|x| x.round}
Money.new(2000, "USD").exchange_to(Currency.new("EUR"))

Parameters:

  • other_currency (Currency, String, Symbol)

    Currency to exchange to.

Yields:

  • (n)

    Optional block to use when rounding after exchanging one currency for another.

Yield Parameters:

  • n (Float)

    The resulting float after exchanging one currency for another.

Yield Returns:

  • (Integer)

Returns:



449
450
451
452
453
454
455
456
# File 'lib/money/money.rb', line 449

def exchange_to(other_currency, &rounding_method)
  other_currency = Currency.wrap(other_currency)
  if self.currency == other_currency
    self
  else
    @bank.exchange_with(self, other_currency, &rounding_method)
  end
end

#fractionalInteger, BigDecimal

The value of the monetary amount represented in the fractional or subunit of the currency.

For example, in the US Dollar currency the fractional unit is cents, and there are 100 cents in one US Dollar. So given the Money representation of one US dollar, the fractional interpretation is 100.

Another example is that of the Kuwaiti Dinar. In this case the fractional unit is the Fils and there 1000 Fils to one Kuwaiti Dinar. So given the Money representation of one Kuwaiti Dinar, the fractional interpretation is 1000.

Returns:

  • (Integer)

    when infinite_precision is false

  • (BigDecimal)

    when infintie_precision is true

See Also:



48
49
50
51
52
53
54
# File 'lib/money/money.rb', line 48

def fractional
  # Ensure we have a BigDecimal. If the Money object is created
  # from YAML, @fractional can end up being set to a Float.
  fractional = as_d(@fractional)

  return_value(fractional)
end

#hashFixnum

Returns a Fixnum hash value based on the fractional and currency attributes in order to use functions like & (intersection), group_by, etc.

Examples:

Money.new(100).hash #=> 908351

Returns:

  • (Fixnum)


345
346
347
# File 'lib/money/money.rb', line 345

def hash
  [fractional.hash, currency.hash].hash
end

#inspectString

Common inspect function

Returns:

  • (String)


362
363
364
# File 'lib/money/money.rb', line 362

def inspect
  "#<Money fractional:#{fractional} currency:#{currency}>"
end

#localize_formatting_rules(rules) ⇒ Object



333
334
335
336
337
338
339
340
# File 'lib/money/money/formatting.rb', line 333

def localize_formatting_rules(rules)
  if currency.iso_code == "JPY" && I18n.locale == :ja
    rules[:symbol] = "" unless rules[:symbol] == false
    rules[:symbol_position] = :after
    rules[:symbol_after_without_space] = true
  end
  rules
end

#regexp_format(formatted, rules, decimal_mark, symbol_value) ⇒ Object



319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/money/money/formatting.rb', line 319

def regexp_format(formatted, rules, decimal_mark, symbol_value)
  regexp_decimal = Regexp.escape(decimal_mark)
  if rules[:south_asian_number_formatting]
    /(\d+?)(?=(\d\d)+(\d)(?:\.))/
  else
    # Symbols may contain decimal marks (E.g "դր.")
    if formatted.sub(symbol_value.to_s, "") =~ /#{regexp_decimal}/
      /(\d)(?=(?:\d{3})+(?:#{regexp_decimal}))/
    else
      /(\d)(?=(?:\d{3})+(?:[^\d]{1}|$))/
    end
  end
end

#round(rounding_mode = self.class.rounding_mode) ⇒ Money

Note:

This method is only useful when operating with infinite_precision turned on. Without infinite_precision values are rounded to the smallest unit of coinage automatically.

Round the monetary amount to smallest unit of coinage.

Examples:

Money.new(10.1, 'USD').round #=> Money.new(10, 'USD')

Returns:

See Also:



556
557
558
559
560
561
562
# File 'lib/money/money.rb', line 556

def round(rounding_mode = self.class.rounding_mode)
  if self.class.infinite_precision
    Money.new(fractional.round(0, rounding_mode), self.currency)
  else
    self
  end
end

#round_to_nearest_cash_valueInteger, BigDecimal

Round a given amount of money to the nearest possible amount in cash value. For example, in Swiss francs (CHF), the smallest possible amount of cash value is CHF 0.05. Therefore, this method rounds CHF 0.07 to CHF 0.05, and CHF 0.08 to CHF 0.10.

Returns:

  • (Integer)

    when infinite_precision is false

  • (BigDecimal)

    when infinite_precision is true

See Also:



65
66
67
68
69
70
71
72
73
74
75
# File 'lib/money/money.rb', line 65

def round_to_nearest_cash_value
  unless self.currency.smallest_denomination
    raise UndefinedSmallestDenomination, 'Smallest denomination of this currency is not defined'
  end

  fractional = as_d(@fractional)
  smallest_denomination = as_d(self.currency.smallest_denomination)
  rounded_value = (fractional / smallest_denomination).round(0, self.class.rounding_mode) * smallest_denomination

  return_value(rounded_value)
end

#split(num) ⇒ Array<Money>

Split money amongst parties evenly without losing pennies.

Examples:

Money.new(100, "USD").split(3) #=> [Money.new(34), Money.new(33), Money.new(33)]

Parameters:

  • num (Numeric)

    number of parties.

Returns:

Raises:

  • (ArgumentError)


531
532
533
534
535
536
537
538
539
# File 'lib/money/money.rb', line 531

def split(num)
  raise ArgumentError, "need at least one party" if num < 1

  if self.class.infinite_precision
    split_infinite(num)
  else
    split_flat(num)
  end
end

#symbolString

Uses Currency#symbol. If nil is returned, defaults to “¤”.

Examples:

Money.new(100, "USD").symbol #=> "$"

Returns:

  • (String)


355
356
357
# File 'lib/money/money.rb', line 355

def symbol
  currency.symbol || "¤"
end

#symbol_position_from(rules) ⇒ Object



360
361
362
363
364
365
366
367
368
# File 'lib/money/money/formatting.rb', line 360

def symbol_position_from(rules)
  if rules.has_key?(:symbol_position)
    rules[:symbol_position]
  elsif currency.symbol_first?
    :before
  else
    :after
  end
end

#symbol_value_from(rules) ⇒ Object



342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/money/money/formatting.rb', line 342

def symbol_value_from(rules)
  if rules.has_key?(:symbol)
    if rules[:symbol] === true
      symbol
    elsif rules[:symbol]
      rules[:symbol]
    else
      ""
    end
  elsif rules[:html]
    currency.html_entity == '' ? currency.symbol : currency.html_entity
  elsif rules[:disambiguate] and currency.disambiguate_symbol
    currency.disambiguate_symbol
  else
    symbol
  end
end

#to_dBigDecimal

Return the amount of money as a BigDecimal.

Examples:

Money.us_dollar(1_00).to_d #=> BigDecimal.new("1.00")

Returns:

  • (BigDecimal)


394
395
396
# File 'lib/money/money.rb', line 394

def to_d
  as_d(fractional) / as_d(currency.subunit_to_unit)
end

#to_fFloat

Return the amount of money as a float. Floating points cannot guarantee precision. Therefore, this function should only be used when you no longer need to represent currency or working with another system that requires floats.

Examples:

Money.us_dollar(100).to_f #=> 1.0

Returns:

  • (Float)


417
418
419
# File 'lib/money/money.rb', line 417

def to_f
  to_d.to_f
end

#to_iInteger

Return the amount of money as a Integer.

Examples:

Money.us_dollar(1_00).to_i #=> 1

Returns:

  • (Integer)


404
405
406
# File 'lib/money/money.rb', line 404

def to_i
  to_d.to_i
end

#to_money(given_currency = nil) ⇒ self

Conversation to self.

Returns:

  • (self)


424
425
426
427
428
429
430
431
# File 'lib/money/money.rb', line 424

def to_money(given_currency = nil)
  given_currency = Currency.wrap(given_currency)
  if given_currency.nil? || self.currency == given_currency
    self
  else
    exchange_to(given_currency)
  end
end

#to_sString

Returns the amount of money as a string.

Examples:

Money.ca_dollar(100).to_s #=> "1.00"

Returns:

  • (String)


372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
# File 'lib/money/money.rb', line 372

def to_s
  unit, subunit, fraction = strings_from_fractional

  str = if currency.decimal_places == 0
          if fraction == ""
            unit
          else
            "#{unit}#{decimal_mark}#{fraction}"
          end
        else
          "#{unit}#{decimal_mark}#{pad_subunit(subunit)}#{fraction}"
        end

  fractional < 0 ? "-#{str}" : str
end