Class: Philiprehberger::Money::Currency

Inherits:
Object
  • Object
show all
Defined in:
lib/philiprehberger/money/currency.rb

Overview

Represents a currency with formatting rules and subunit information

Constant Summary collapse

REGISTRY =
{
  usd: new(code: :usd, name: 'US Dollar', symbol: '$', subunit_to_unit: 100),
  eur: new(code: :eur, name: 'Euro', symbol: "\u20AC", subunit_to_unit: 100, symbol_first: true,
           decimal_separator: ',', thousands_separator: '.'),
  gbp: new(code: :gbp, name: 'British Pound', symbol: "\u00A3", subunit_to_unit: 100),
  jpy: new(code: :jpy, name: 'Japanese Yen', symbol: "\u00A5", subunit_to_unit: 1),
  cad: new(code: :cad, name: 'Canadian Dollar', symbol: '$', subunit_to_unit: 100),
  aud: new(code: :aud, name: 'Australian Dollar', symbol: '$', subunit_to_unit: 100),
  chf: new(code: :chf, name: 'Swiss Franc', symbol: 'CHF', subunit_to_unit: 100, symbol_first: true,
           decimal_separator: '.', thousands_separator: "'"),
  cny: new(code: :cny, name: 'Chinese Yuan', symbol: "\u00A5", subunit_to_unit: 100),
  inr: new(code: :inr, name: 'Indian Rupee', symbol: "\u20B9", subunit_to_unit: 100),
  brl: new(code: :brl, name: 'Brazilian Real', symbol: 'R$', subunit_to_unit: 100, symbol_first: true,
           decimal_separator: ',', thousands_separator: '.'),
  mxn: new(code: :mxn, name: 'Mexican Peso', symbol: '$', subunit_to_unit: 100),
  krw: new(code: :krw, name: 'South Korean Won', symbol: "\u20A9", subunit_to_unit: 1),
  sek: new(code: :sek, name: 'Swedish Krona', symbol: 'kr', subunit_to_unit: 100, symbol_first: false,
           decimal_separator: ',', thousands_separator: ' '),
  nok: new(code: :nok, name: 'Norwegian Krone', symbol: 'kr', subunit_to_unit: 100, symbol_first: false,
           decimal_separator: ',', thousands_separator: ' '),
  dkk: new(code: :dkk, name: 'Danish Krone', symbol: 'kr', subunit_to_unit: 100, symbol_first: false,
           decimal_separator: ',', thousands_separator: '.'),
  pln: new(code: :pln, name: 'Polish Zloty', symbol: "z\u0142", subunit_to_unit: 100, symbol_first: false,
           decimal_separator: ',', thousands_separator: ' '),
  czk: new(code: :czk, name: 'Czech Koruna', symbol: "K\u010D", subunit_to_unit: 100, symbol_first: false,
           decimal_separator: ',', thousands_separator: ' '),
  huf: new(code: :huf, name: 'Hungarian Forint', symbol: 'Ft', subunit_to_unit: 100, symbol_first: false,
           decimal_separator: ',', thousands_separator: ' '),
  try: new(code: :try, name: 'Turkish Lira', symbol: "\u20BA", subunit_to_unit: 100),
  zar: new(code: :zar, name: 'South African Rand', symbol: 'R', subunit_to_unit: 100),
  nzd: new(code: :nzd, name: 'New Zealand Dollar', symbol: '$', subunit_to_unit: 100),
  sgd: new(code: :sgd, name: 'Singapore Dollar', symbol: '$', subunit_to_unit: 100),
  hkd: new(code: :hkd, name: 'Hong Kong Dollar', symbol: 'HK$', subunit_to_unit: 100),
  twd: new(code: :twd, name: 'New Taiwan Dollar', symbol: 'NT$', subunit_to_unit: 100),
  thb: new(code: :thb, name: 'Thai Baht', symbol: "\u0E3F", subunit_to_unit: 100),
  rub: new(code: :rub, name: 'Russian Ruble', symbol: "\u20BD", subunit_to_unit: 100),
  ils: new(code: :ils, name: 'Israeli Shekel', symbol: "\u20AA", subunit_to_unit: 100),
  aed: new(code: :aed, name: 'UAE Dirham', symbol: "\u062F.\u0625", subunit_to_unit: 100),
  sar: new(code: :sar, name: 'Saudi Riyal', symbol: "\uFDFC", subunit_to_unit: 100),
  php: new(code: :php, name: 'Philippine Peso', symbol: "\u20B1", subunit_to_unit: 100)
}.freeze

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(code:, name:, symbol:, subunit_to_unit:, symbol_first: true, decimal_separator: '.', thousands_separator: ',') ⇒ Currency

Returns a new instance of Currency.

Parameters:

  • code (Symbol)

    ISO 4217 currency code (lowercase)

  • name (String)

    full currency name

  • symbol (String)

    currency symbol

  • subunit_to_unit (Integer)

    number of subunits per unit (100 for cents, 1 for zero-decimal)

  • symbol_first (Boolean) (defaults to: true)

    whether the symbol appears before the amount

  • decimal_separator (String) (defaults to: '.')

    character separating decimals

  • thousands_separator (String) (defaults to: ',')

    character separating thousands



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/philiprehberger/money/currency.rb', line 16

def initialize(code:, name:, symbol:, subunit_to_unit:, symbol_first: true,
               decimal_separator: '.', thousands_separator: ',')
  @code = code
  @name = name
  @symbol = symbol
  @subunit_to_unit = subunit_to_unit
  @symbol_first = symbol_first
  @decimal_separator = decimal_separator
  @thousands_separator = thousands_separator
  freeze
end

Class Attribute Details

.custom_currenciesObject (readonly)

Returns the value of attribute custom_currencies.



79
80
81
# File 'lib/philiprehberger/money/currency.rb', line 79

def custom_currencies
  @custom_currencies
end

Instance Attribute Details

#codeObject (readonly)

Returns the value of attribute code.



7
8
9
# File 'lib/philiprehberger/money/currency.rb', line 7

def code
  @code
end

#decimal_separatorObject (readonly)

Returns the value of attribute decimal_separator.



7
8
9
# File 'lib/philiprehberger/money/currency.rb', line 7

def decimal_separator
  @decimal_separator
end

#nameObject (readonly)

Returns the value of attribute name.



7
8
9
# File 'lib/philiprehberger/money/currency.rb', line 7

def name
  @name
end

#subunit_to_unitObject (readonly)

Returns the value of attribute subunit_to_unit.



7
8
9
# File 'lib/philiprehberger/money/currency.rb', line 7

def subunit_to_unit
  @subunit_to_unit
end

#symbolObject (readonly)

Returns the value of attribute symbol.



7
8
9
# File 'lib/philiprehberger/money/currency.rb', line 7

def symbol
  @symbol
end

#symbol_firstObject (readonly)

Returns the value of attribute symbol_first.



7
8
9
# File 'lib/philiprehberger/money/currency.rb', line 7

def symbol_first
  @symbol_first
end

#thousands_separatorObject (readonly)

Returns the value of attribute thousands_separator.



7
8
9
# File 'lib/philiprehberger/money/currency.rb', line 7

def thousands_separator
  @thousands_separator
end

Class Method Details

.find(code) ⇒ Currency

Find a currency by its code

Parameters:

  • code (Symbol, String)

    currency code (e.g. :usd, “USD”)

Returns:

Raises:



33
34
35
36
37
38
39
40
# File 'lib/philiprehberger/money/currency.rb', line 33

def self.find(code)
  key = code.to_s.downcase.to_sym
  REGISTRY.fetch(key) do
    @custom_currencies.fetch(key) do
      raise Philiprehberger::Money::InvalidCurrency, "Unknown currency: #{code}"
    end
  end
end

.register(code:, name:, symbol:, subunit_to_unit: 100, symbol_first: true, decimal_separator: '.', thousands_separator: ',') ⇒ Currency

Register a custom currency

Parameters:

  • code (Symbol, String)

    currency code (3+ uppercase letters)

  • name (String)

    full currency name

  • symbol (String)

    currency symbol

  • subunit_to_unit (Integer) (defaults to: 100)

    number of subunits per unit (default: 100)

  • symbol_first (Boolean) (defaults to: true)

    whether the symbol appears before the amount

  • decimal_separator (String) (defaults to: '.')

    character separating decimals

  • thousands_separator (String) (defaults to: ',')

    character separating thousands

Returns:

Raises:

  • (ArgumentError)

    if code format is invalid or already registered



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/philiprehberger/money/currency.rb', line 53

def self.register(code:, name:, symbol:, subunit_to_unit: 100, symbol_first: true,
                  decimal_separator: '.', thousands_separator: ',')
  code_str = code.to_s.upcase
  raise ArgumentError, 'Currency code must be 3 or more uppercase letters' unless code_str.match?(/\A[A-Z]{3,}\z/)
  raise ArgumentError, 'subunit_to_unit must be a positive integer' unless subunit_to_unit.is_a?(Integer) && subunit_to_unit.positive?

  key = code_str.downcase.to_sym
  if REGISTRY.key?(key) || @custom_currencies.key?(key)
    raise ArgumentError, "Currency already registered: #{code_str}"
  end

  currency = new(
    code: key,
    name: name,
    symbol: symbol,
    subunit_to_unit: subunit_to_unit,
    symbol_first: symbol_first,
    decimal_separator: decimal_separator,
    thousands_separator: thousands_separator
  )
  @custom_currencies[key] = currency
  currency
end

.reset_custom_currencies!Object

Reset custom currencies (useful for testing)



83
84
85
# File 'lib/philiprehberger/money/currency.rb', line 83

def self.reset_custom_currencies!
  @custom_currencies = {}
end