Module: Invoicing::CurrencyValue::Formatter

Defined in:
lib/invoicing/currency_value.rb

Overview

Encapsulates the methods for formatting currency values in a human-friendly way. These methods do not depend on ActiveRecord and can thus also be called externally.

Class Method Summary collapse

Class Method Details

.currency_info(code, options = {}) ⇒ Object

Given the three-letter ISO 4217 code of a currency, returns a hash with useful bits of information:

:code

The ISO 4217 code of the currency.

:round

Smallest unit of the currency in normal use, to which values are rounded. Default is 0.01.

:symbol

Symbol or string usually used to denote the currency. Encoded as UTF-8. Default is ISO 4217 code.

:suffix

true if the currency symbol appears after the number, false if it appears before.

:space

Whether or not to leave a space between the number and the currency symbol.

:digits

Number of digits to display after the decimal point.



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/invoicing/currency_value.rb', line 156

def currency_info(code, options={})
  code = code.to_s.upcase
  valid_options = [:symbol, :round, :suffix, :space, :digits]
  info = {:code => code, :symbol => code, :round => 0.01, :suffix => nil, :space => nil, :digits => nil}
  if ::Invoicing::CurrencyValue::CURRENCIES.has_key? code
    info.update(::Invoicing::CurrencyValue::CURRENCIES[code])
  end
  options.each_pair {|key, value| info[key] = value if valid_options.include? key }

  info[:suffix] ||= (info[:code] == info[:symbol]) && !info[:code].nil?
  info[:space]  ||= info[:suffix]
  info[:digits] = -Math.log10(info[:round]).floor if info[:digits].nil?
  info[:digits] = 0 if info[:digits] < 0

  info
end

.format_value(currency_code, value, options = {}) ⇒ Object

Given the three-letter ISO 4217 code of a currency and a BigDecimal value, returns the value formatted as an UTF-8 string, ready for human consumption.

FIXME: This method currently does not take locale into account – it always uses the dot as decimal separator and the comma as thousands separator.



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/invoicing/currency_value.rb', line 178

def format_value(currency_code, value, options={})
  info = currency_info(currency_code, options)

  negative = false
  if value < 0
    negative = true
    value = -value
  end

  value = "%.#{info[:digits]}f" % value
  while value.sub!(/(\d+)(\d\d\d)/, '\1,\2'); end
  value.sub!(/^\-/, '') # avoid displaying minus zero

  formatted = if ['', nil].include? info[:symbol]
    value
  elsif info[:space]
    info[:suffix] ? "#{value} #{info[:symbol]}" : "#{info[:symbol]} #{value}"
  else
    info[:suffix] ? "#{value}#{info[:symbol]}" : "#{info[:symbol]}#{value}"
  end

  if negative
    # default is to use proper unicode minus sign
    formatted = (options[:negative] == :brackets) ? "(#{formatted})" : (
      (options[:negative] == :hyphen) ? "-#{formatted}" : "\xE2\x88\x92#{formatted}"
    )
  end
  formatted.force_encoding("utf-8")
end