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.



35
36
37
38
39
40
41
# File 'lib/amount/registry.rb', line 35

def initialize
  @entries = {}
  @default_rates = {}
  @generated_constructors = GeneratedConstructors.new
  @locked = false
  @lock = Mutex.new
end

Instance Method Details

#activate_generated_methods!void

This method returns an undefined value.



201
202
203
204
205
# File 'lib/amount/registry.rb', line 201

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:



129
130
131
132
133
134
135
136
# File 'lib/amount/registry.rb', line 129

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:



165
166
167
168
169
170
171
# File 'lib/amount/registry.rb', line 165

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)


179
180
181
# File 'lib/amount/registry.rb', line 179

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!


186
187
188
189
190
# File 'lib/amount/registry.rb', line 186

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

#locked?Boolean

Examples:

Amount.registry.locked?
# => true

Returns:

  • (Boolean)


196
197
198
# File 'lib/amount/registry.rb', line 196

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

#lookup(symbol) ⇒ Entry

Examples:

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

Parameters:

  • symbol (Symbol, String)

Returns:

Raises:



109
110
111
112
113
114
115
# File 'lib/amount/registry.rb', line 109

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, 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

  • 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



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/amount/registry.rb', line 67

def register(symbol, decimals:, display_symbol: symbol.to_s, display_position: :suffix,
             ui_decimals: decimals, display_units: nil, default_display: nil,
             class: nil)
  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
    )

    @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:



145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/amount/registry.rb', line 145

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]] = BigDecimal(rate.to_s)
  end
end

#registered?(symbol) ⇒ Boolean

Examples:

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

Parameters:

  • symbol (Symbol, String)

Returns:

  • (Boolean)


99
100
101
# File 'lib/amount/registry.rb', line 99

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

#remove_generated_methods!void

This method returns an undefined value.



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

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

#symbolsArray<Symbol>

Examples:

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

Returns:

  • (Array<Symbol>)


121
122
123
# File 'lib/amount/registry.rb', line 121

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