Module: Money::Formatting

Included in:
Money
Defined in:
lib/money/money/formatting.rb

Instance Method Summary collapse

Instance Method Details

#decimal_markObject Also known as: separator



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

def decimal_mark
  i18n_format_for(:decimal_mark, :separator, ".")
end

#format(*rules) ⇒ String

Creates a formatted price string according to several rules.

Note that the default rules can be defined through Money.default_formatting_rules hash.

Examples:

Money.us_dollar(0).format(:display_free => true)     #=> "free"
Money.us_dollar(0).format(:display_free => "gratis") #=> "gratis"
Money.us_dollar(0).format                            #=> "$0.00"
Money.ca_dollar(100).format #=> "$1.00"
Money.ca_dollar(100).format(:with_currency => true) #=> "$1.00 CAD"
Money.us_dollar(85).format(:with_currency => true)  #=> "$0.85 USD"
Money.us_dollar(100.1).format #=> "$1.001"
Money.us_dollar(100.1).format(:rounded_infinite_precision => true) #=> "$1"
Money.us_dollar(100.9).format(:rounded_infinite_precision => true) #=> "$1.01"
Money.ca_dollar(100).format(:no_cents => true) #=> "$1"
Money.ca_dollar(599).format(:no_cents => true) #=> "$5"
Money.ca_dollar(10000).format(:no_cents_if_whole => true) #=> "$100"
Money.ca_dollar(10034).format(:no_cents_if_whole => true) #=> "$100.34"
Money.new(100, "USD") #=> "$1.00"
Money.new(100, "GBP") #=> "£1.00"
Money.new(100, "EUR") #=> "€1.00"

# Same thing.
Money.new(100, "USD").format(:symbol => true) #=> "$1.00"
Money.new(100, "GBP").format(:symbol => true) #=> "£1.00"
Money.new(100, "EUR").format(:symbol => true) #=> "€1.00"

# You can specify a false expression or an empty string to disable
# prepending a money symbol.§
Money.new(100, "USD").format(:symbol => false) #=> "1.00"
Money.new(100, "GBP").format(:symbol => nil)   #=> "1.00"
Money.new(100, "EUR").format(:symbol => "")    #=> "1.00"

# If the symbol for the given currency isn't known, then it will default
# to "¤" as symbol.
Money.new(100, "AWG").format(:symbol => true) #=> "¤1.00"

# You can specify a string as value to enforce using a particular symbol.
Money.new(100, "AWG").format(:symbol => "ƒ") #=> "ƒ1.00"

# You can specify a indian currency format
Money.new(10000000, "INR").format(:south_asian_number_formatting => true) #=> "1,00,000.00"
Money.new(10000000).format(:south_asian_number_formatting => true) #=> "$1,00,000.00"
# Default is to not insert a space.
Money.new(100, "USD").format #=> "$1.00"

# Same thing.
Money.new(100, "USD").format(:symbol_before_without_space => true) #=> "$1.00"

# If set to false, will insert a space.
Money.new(100, "USD").format(:symbol_before_without_space => false) #=> "$ 1.00"
# Default is to insert a space.
Money.new(100, "USD").format(:symbol_position => :after) #=> "1.00 $"

# If set to true, will not insert a space.
Money.new(100, "USD").format(:symbol_position => :after, :symbol_after_without_space => true) #=> "1.00$"
# If a string is specified, it's value is used.
Money.new(100, "USD").format(:decimal_mark => ",") #=> "$1,00"

# If the decimal_mark for a given currency isn't known, then it will default
# to "." as decimal_mark.
Money.new(100, "FOO").format #=> "$1.00"
# If false is specified, no thousands_separator is used.
Money.new(100000, "USD").format(:thousands_separator => false) #=> "1000.00"
Money.new(100000, "USD").format(:thousands_separator => nil)   #=> "1000.00"
Money.new(100000, "USD").format(:thousands_separator => "")    #=> "1000.00"

# If a string is specified, it's value is used.
Money.new(100000, "USD").format(:thousands_separator => ".") #=> "$1.000.00"

# If the thousands_separator for a given currency isn't known, then it will
# default to "," as thousands_separator.
Money.new(100000, "FOO").format #=> "$1,000.00"
Money.ca_dollar(570).format(:html => true, :with_currency => true)
#=> "$5.70 <span class=\"currency\">CAD</span>"
# You can specify to display the sign before the symbol for negative numbers
Money.new(-100, "GBP").format(:sign_before_symbol => true)  #=> "-£1.00"
Money.new(-100, "GBP").format(:sign_before_symbol => false) #=> "£-1.00"
Money.new(-100, "GBP").format                               #=> "£-1.00"
# You can specify to display the sign with positive numbers
Money.new(100, "GBP").format(:sign_positive => true,  :sign_before_symbol => true)  #=> "+£1.00"
Money.new(100, "GBP").format(:sign_positive => true,  :sign_before_symbol => false) #=> "£+1.00"
Money.new(100, "GBP").format(:sign_positive => false, :sign_before_symbol => true)  #=> "£1.00"
Money.new(100, "GBP").format(:sign_positive => false, :sign_before_symbol => false) #=> "£1.00"
Money.new(100, "GBP").format                               #=> "£+1.00"
Money.new(10000, "USD").format(:disambiguate => false)   #=> "$100.00"
Money.new(10000, "CAD").format(:disambiguate => false)   #=> "$100.00"
Money.new(10000, "USD").format(:disambiguate => true)    #=> "$100.00"
Money.new(10000, "CAD").format(:disambiguate => true)    #=> "C$100.00"
Money.new(10000, "USD").format(:disambiguate => false)
#=> "<span class=\"currency_symbol\">$100.00</span>
Money.new(10000, "USD").format(:symbol_position => :before) #=> "$100.00"
Money.new(10000, "USD").format(:symbol_position => :after)  #=> "100.00 $"
# With the following entry in the translation files:
# en:
#   number:
#     currency:
#       symbol:
#         CAD: "CAD$"
Money.new(10000, "CAD").format(:translate => true) #=> "CAD$100.00"
Money.new(89000, :btc).format(:drop_trailing_zeros => true) #=> B⃦0.00089
Money.new(110, :usd).format(:drop_trailing_zeros => true)   #=> $1.1

Parameters:

  • rules (Hash)

    The options used to format the string.

Options Hash (*rules):

  • :display_free (Boolean, String) — default: false

    Whether a zero amount of money should be formatted of “free” or as the supplied string.

  • :with_currency (Boolean) — default: false

    Whether the currency name should be appended to the result string.

  • :rounded_infinite_precision (Boolean) — default: false

    Whether the amount of money should be rounded when using Money.infinite_precision

  • :no_cents (Boolean) — default: false

    Whether cents should be omitted.

  • :no_cents_if_whole (Boolean) — default: false

    Whether cents should be omitted if the cent value is zero

  • :symbol (Boolean, String, nil) — default: true

    Whether a money symbol should be prepended to the result string. The default is true. This method attempts to pick a symbol that’s suitable for the given currency.

  • :symbol_before_without_space (Boolean, nil) — default: true

    Whether a space between the money symbol and the amount should be inserted when :symbol_position is :before. The default is true (meaning no space). Ignored if :symbol is false or :symbol_position is not :before.

  • :symbol_after_without_space (Boolean, nil) — default: false

    Whether a space between the amount and the money symbol should be inserted when :symbol_position is :after. The default is false (meaning space). Ignored if :symbol is false or :symbol_position is not :after.

  • :decimal_mark (Boolean, String, nil) — default: true

    Whether the currency should be separated by the specified character or ‘.’

  • :thousands_separator (Boolean, String, nil) — default: true

    Whether the currency should be delimited by the specified character or ‘,’

  • :html (Boolean) — default: false

    Whether the currency should be HTML-formatted. Only useful in combination with :with_currency.

  • :sign_before_symbol (Boolean) — default: false

    Whether the sign should be before the currency symbol.

  • :sign_positive (Boolean) — default: false

    Whether positive numbers should be signed, too.

  • :disambiguate (Boolean) — default: false

    Prevents the result from being ambiguous due to equal symbols for different currencies. Uses the ‘disambiguate_symbol`.

  • :html_wrap_symbol (Boolean) — default: false

    Wraps the currency symbol in a html <span> tag.

  • :symbol_position (Symbol) — default: :before

    ‘:before` if the currency symbol goes before the amount, `:after` if it goes after.

  • :translate (Boolean) — default: true

    ‘true` Checks for custom symbol definitions using I18n.

Returns:

See Also:



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/money/money/formatting.rb', line 201

def format(*rules)
  # support for old format parameters
  rules = normalize_formatting_rules(rules)

  rules = default_formatting_rules.merge(rules)
  rules = localize_formatting_rules(rules)
  rules = translate_formatting_rules(rules) if rules[:translate]

  thousands_separator = self.thousands_separator
  decimal_mark = self.decimal_mark

  escaped_decimal_mark = Regexp.escape(decimal_mark)

  if fractional == 0
    if rules[:display_free].respond_to?(:to_str)
      return rules[:display_free]
    elsif rules[:display_free]
      return "free"
    end
  end

  symbol_value = symbol_value_from(rules)

  formatted = self.abs.to_s

  if rules[:rounded_infinite_precision]
    formatted.gsub!(/#{decimal_mark}/, '.') unless '.' == decimal_mark
    formatted = ((BigDecimal(formatted) * currency.subunit_to_unit).round / BigDecimal(currency.subunit_to_unit.to_s)).to_s("F")
    formatted.gsub!(/\..*/) do |decimal_part|
      decimal_part << '0' while decimal_part.length < (currency.decimal_places + 1)
      decimal_part
    end
    formatted.gsub!(/\./, decimal_mark) unless '.' == decimal_mark
  end

  sign = self.negative? ? '-' : ''

  if rules[:no_cents] || (rules[:no_cents_if_whole] && cents % currency.subunit_to_unit == 0)
    formatted = "#{formatted.to_i}"
  end

  # Inspiration: https://github.com/rails/rails/blob/16214d1108c31174c94503caced3855b0f6bad95/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb#L72-L79
  if rules[:drop_trailing_zeros]
    formatted = formatted.sub(/(#{escaped_decimal_mark})(\d*[1-9])?0+\z/, '\1\2').sub(/#{escaped_decimal_mark}\z/, '')
  end
  has_decimal_value = !!(formatted =~ /#{escaped_decimal_mark}/)

  thousands_separator_value = thousands_separator
  # Determine thousands_separator
  if rules.has_key?(:thousands_separator)
    thousands_separator_value = rules[:thousands_separator] || ''
  end

  # Apply thousands_separator
  formatted.gsub!(regexp_format(formatted, rules, decimal_mark, symbol_value),
                  "\\1#{thousands_separator_value}")

  symbol_position = symbol_position_from(rules)

  if rules[:sign_positive] == true && self.positive?
    sign = '+'
  end

  if rules[:sign_before_symbol] == true
    sign_before = sign
    sign = ''
  end

  if symbol_value && !symbol_value.empty?
    symbol_value = "<span class=\"currency_symbol\">#{symbol_value}</span>" if rules[:html_wrap_symbol]

    formatted = if symbol_position == :before
      symbol_space = rules[:symbol_before_without_space] === false ? " " : ""
      "#{sign_before}#{symbol_value}#{symbol_space}#{sign}#{formatted}"
    else
      symbol_space = rules[:symbol_after_without_space] ? "" : " "
      "#{sign_before}#{sign}#{formatted}#{symbol_space}#{symbol_value}"
    end
  else
    formatted="#{sign_before}#{sign}#{formatted}"
  end

  apply_decimal_mark_from_rules(formatted, rules) if has_decimal_value

  if rules[:with_currency]
    formatted << " "
    formatted << '<span class="currency">' if rules[:html]
    formatted << currency.to_s
    formatted << '</span>' if rules[:html]
  end
  formatted
end

#thousands_separatorObject Also known as: delimiter



294
295
296
# File 'lib/money/money/formatting.rb', line 294

def thousands_separator
  i18n_format_for(:thousands_separator, :delimiter, ",")
end