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.



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/invoicing/currency_value.rb', line 149

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.



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/invoicing/currency_value.rb', line 171

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
end