Class: Amount::Registry

Inherits:
Object
  • Object
show all
Defined in:
lib/amount/registry.rb,
lib/amount/registry/generated_constructors.rb

Overview

Stores registered amount types and default directional conversion rates.

The registry is the configuration surface of the gem. Application code normally uses the shared global instance exposed by registry, configures it during boot, and optionally calls #lock! when setup is complete.

Examples:

Registering types at boot

Amount.register :USDC, decimals: 6

Amount.register :USD, decimals: 2

Amount.register_default_rate :USD, :USDC, "1"
Amount.registry.lock!

Defined Under Namespace

Classes: AlreadyRegistered, Entry, GeneratedConstructors, InvalidDisplayUnit, NoDefaultRate, RegistryLocked, UnknownType

Instance Method Summary collapse

Constructor Details

#initializeRegistry

Returns a new instance of Registry.



42
43
44
45
46
47
48
49
# File 'lib/amount/registry.rb', line 42

def initialize
  @entries       = {}
  @default_rates = {}
  @locked        = false

  @lock = Mutex.new
  @generated_constructors = GeneratedConstructors.new
end

Instance Method Details

#activate_generated_methods!void

This method returns an undefined value.



213
214
215
216
217
# File 'lib/amount/registry.rb', line 213

def activate_generated_methods!
  @lock.synchronize do
    @generated_constructors.activate(@entries)
  end
end

#clear!void

This method returns an undefined value.

Examples:

Amount.registry.clear!

Raises:



141
142
143
144
145
146
147
148
# File 'lib/amount/registry.rb', line 141

def clear!
  @lock.synchronize do
    ensure_unlocked!
    @generated_constructors.remove_all
    @entries.clear
    @default_rates.clear
  end
end

#default_rate(from, to) ⇒ BigDecimal

Examples:

Amount.registry.default_rate(:USD, :USDC)
# => 0.1e1

Parameters:

  • from (Symbol, String)
  • to (Symbol, String)

Returns:

  • (BigDecimal)

Raises:



177
178
179
180
181
182
183
# File 'lib/amount/registry.rb', line 177

def default_rate(from, to)
  @lock.synchronize do
    @default_rates.fetch([from.to_sym, to.to_sym]) do
      raise NoDefaultRate, "no default rate for #{from} -> #{to}; pass rate: explicitly"
    end
  end
end

#default_rate?(from, to) ⇒ Boolean

Examples:

Amount.registry.default_rate?(:USD, :USDC)
# => true

Parameters:

  • from (Symbol, String)
  • to (Symbol, String)

Returns:

  • (Boolean)


191
192
193
# File 'lib/amount/registry.rb', line 191

def default_rate?(from, to)
  @lock.synchronize { @default_rates.key?([from.to_sym, to.to_sym]) }
end

#lock!void

This method returns an undefined value.

Examples:

Locking the global registry after initialization

Amount.registry.lock!


198
199
200
201
202
# File 'lib/amount/registry.rb', line 198

def lock!
  @lock.synchronize do
    @locked = true
  end
end

#locked?Boolean

Examples:

Amount.registry.locked?
# => true

Returns:

  • (Boolean)


208
209
210
# File 'lib/amount/registry.rb', line 208

def locked?
  @lock.synchronize { @locked }
end

#lookup(symbol) ⇒ Entry

Examples:

Amount.registry.lookup(:USDC).decimals
# => 6

Parameters:

  • symbol (Symbol, String)

Returns:

Raises:



121
122
123
124
125
126
127
# File 'lib/amount/registry.rb', line 121

def lookup(symbol)
  @lock.synchronize do
    @entries.fetch(symbol.to_sym) do
      raise UnknownType, "#{symbol} is not registered"
    end
  end
end

#register(symbol, decimals:, display_symbol: symbol.to_s, display_position: :suffix, ui_decimals: decimals, display_units: nil, default_display: nil, trim_zeros: false, class: nil) ⇒ void

This method returns an undefined value.

Registers a new fungible type.

When the symbol is a valid Ruby method name after downcasing, an ergonomic constructor is also generated on ‘Amount`, such as `Amount.usdc(“1.50”)`.

Examples:

Amount.register :USDC,
  decimals: 6,
  display_symbol: "$",
  display_position: :prefix,
  ui_decimals: 2

Parameters:

  • symbol (Symbol, String)

    registered type identifier

  • decimals (Integer)

    number of storage decimals

  • display_symbol (String) (defaults to: symbol.to_s)

    symbol used by UI helpers

  • display_position (Symbol) (defaults to: :suffix)

    either ‘:prefix` or `:suffix`

  • ui_decimals (Integer) (defaults to: decimals)

    decimals displayed by default UI formatting

  • display_units (Hash, nil) (defaults to: nil)

    optional display-only scaling definitions

  • default_display (Symbol, nil) (defaults to: nil)

    optional default display unit key

  • trim_zeros (Boolean) (defaults to: false)

    strip trailing zeros from UI output

  • class (Class, nil) (defaults to: nil)

    optional custom ‘Amount` subclass

Raises:

  • (AlreadyRegistered)

    if the symbol is already registered or the generated constructor would collide with an existing method

  • (RegistryLocked)

    if the registry has been locked



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/amount/registry.rb', line 76

def register(symbol, decimals:, display_symbol: symbol.to_s, display_position: :suffix,
             ui_decimals: decimals, display_units: nil, default_display: nil,
             trim_zeros: false, class: nil)
  raise ArgumentError, "symbol must not be blank" if symbol.nil? || symbol.to_s.empty?

  symbol = symbol.to_sym

  @lock.synchronize do
    ensure_unlocked!
    raise AlreadyRegistered, "#{symbol} already registered" if @entries.key?(symbol)

    validate_display_units!(display_units, default_display) if display_units

    entry = Entry.new(
      symbol:,
      decimals:,
      display_symbol:,
      display_position:,
      ui_decimals:,
      display_units:,
      default_display:,
      amount_class: binding.local_variable_get(:class) || Amount,
      trim_zeros:
    )

    @entries[symbol] = entry
    @generated_constructors.define_for(entry)
  end
end

#register_default_rate(from, to, rate) ⇒ void

This method returns an undefined value.

Examples:

Amount.register_default_rate :USD, :USDC, "1"

Parameters:

  • from (Symbol, String)
  • to (Symbol, String)
  • rate (String, Numeric, BigDecimal)

Raises:



157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/amount/registry.rb', line 157

def register_default_rate(from, to, rate)
  from = from.to_sym
  to = to.to_sym

  lookup(from)
  lookup(to)

  @lock.synchronize do
    ensure_unlocked!
    @default_rates[[from, to]] = Amount.coerce_decimal(rate)
  end
end

#registered?(symbol) ⇒ Boolean

Examples:

Amount.registry.registered?(:USDC)
# => true

Parameters:

  • symbol (Symbol, String)

Returns:

  • (Boolean)


111
112
113
# File 'lib/amount/registry.rb', line 111

def registered?(symbol)
  @lock.synchronize { @entries.key?(symbol.to_sym) }
end

#remove_generated_methods!void

This method returns an undefined value.



220
221
222
223
224
# File 'lib/amount/registry.rb', line 220

def remove_generated_methods!
  @lock.synchronize do
    @generated_constructors.remove_all
  end
end

#symbolsArray<Symbol>

Examples:

Amount.registry.symbols
# => [:USDC, :USD]

Returns:

  • (Array<Symbol>)


133
134
135
# File 'lib/amount/registry.rb', line 133

def symbols
  @lock.synchronize { @entries.keys }
end