class Latinum::Bank
A bank defines exchange rates and formatting rules for resources. It is a centralised location for resource formatting and metadata.
Attributes
The supported currents and assocaited formatting details. @attribute [Hash(String, Hash)]
A map of all recognised symbols ordered by priority. @attribute [Hash(String, Tuple(Integer, Name))]
Public Class Methods
Imports all given currencies.
# File lib/latinum/bank.rb, line 37 def initialize(*imports) @rates = [] @exchange = {} # This implementation may change: @currencies = {} @formatters = {} # Symbols and their associated priorities @symbols = {} imports&.each do |resources| import(resources) end end
Public Instance Methods
Add an exchange rate to the bank. @parameter rate [ExchangeRate] The exchange rate to add.
# File lib/latinum/bank.rb, line 88 def <<(rate) @rates << rate @exchange[rate.input] ||= {} @exchange[rate.input][rate.output] = rate end
Look up a currency by name.
# File lib/latinum/bank.rb, line 72 def [](name) @currencies[name] end
# File lib/latinum/bank.rb, line 135 def dump(resource) resource.to_s if resource end
Exchange one resource for another using internally specified rates.
# File lib/latinum/bank.rb, line 96 def exchange(resource, for_name) unless rate = @exchange.dig(resource.name, for_name) raise ArgumentError.new("Rate #{rate} unavailable") end config = self[for_name] return resource.exchange(rate.factor, for_name, config[:precision]) end
Format a resource as a string according to the loaded currencies. @parameter resource [Resource] The resource to format.
# File lib/latinum/bank.rb, line 160 def format(resource, *arguments, **options) unless formatter = @formatters[resource.name] raise ArgumentError.new("No formatter found for #{resource.name}") end formatter.format(resource.amount, *arguments, **options) end
Convert the resource from an integral representation based on the currency’s precision. @parameter amount [Integer] The integral resource amount. @parameter name [String] The resource name. @returns [Resource] The converted resource.
# File lib/latinum/bank.rb, line 181 def from_integral(amount, name) formatter = @formatters[name] Resource.new(formatter.from_integral(amount), name) end
Import a list of resource templates, e.g. currencies.
# File lib/latinum/bank.rb, line 54 def import(resources) resources.each do |name, config| name = (config[:name] || name).to_s @currencies[name] = config # Create a formatter: @formatters[name] = config[:formatter].new(**config) if config[:symbol] symbols = (@symbols[config[:symbol]] ||= []) symbols << [config.fetch(:priority, -1), name.to_s] symbols.sort!.uniq! end end end
# File lib/latinum/bank.rb, line 128 def load(input) if input.is_a?(String) input = input.strip return parse(input) unless input.empty? end end
Parse a string according to the loaded currencies.
# File lib/latinum/bank.rb, line 107 def parse(string, default_name: nil) parts = string.strip.split(/\s+/, 2) if parts.size == 2 return parse_named_resource(parts[1], parts[0]) else # Lookup the named symbol, e.g. '$', and get the highest priority name: symbol = @symbols.fetch(string.gsub(/[\-\.,0-9]/, ''), []).last if symbol name = symbol.last.to_s elsif default_name name = default_name else raise ArgumentError, "Could not parse #{string}, could not determine resource name!" end return parse_named_resource(name, string) end end
Rounds the specified resource to the maximum precision as specified by the formatter. Whe computing things like tax, you often get fractional amounts which are unpayable because they are smaller than the minimum discrete unit of the currency. This method helps to round a currency to a payable amount. @parameter resource [Resource] The resource to round. @returns [Resource] A copy of the resource with the amount rounded as per the formatter.
# File lib/latinum/bank.rb, line 150 def round(resource) unless formatter = @formatters[resource.name] raise ArgumentError.new("No formatter found for #{resource.name}") end return Resource.new(formatter.round(resource.amount), resource.name) end
Convert the resource to an integral representation based on the currency’s precision. @parameter resource [Resource] The resource to convert. @returns [Integer] The integer representation.
# File lib/latinum/bank.rb, line 171 def to_integral(resource) formatter = @formatters[resource.name] formatter.to_integral(resource.amount) end
Private Instance Methods
# File lib/latinum/bank.rb, line 139 def parse_named_resource(name, value) if formatter = @formatters[name] return Resource.new(formatter.parse(value), name) else raise ArgumentError, "No formatter found for #{name}!" end end