Class: Latinum::Bank

Inherits:
Object
  • Object
show all
Defined in:
lib/latinum/bank.rb

Overview

A bank defines exchange rates and formatting rules for resources. It is a centralised location for resource formatting and metadata.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*imports) ⇒ Bank

Imports all given currencies.



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/latinum/bank.rb', line 53

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

Instance Attribute Details

#currenciesObject (readonly)

The supported currents and assocaited formatting details.



100
101
102
# File 'lib/latinum/bank.rb', line 100

def currencies
  @currencies
end

#ratesObject (readonly)

Returns the value of attribute rates.



92
93
94
# File 'lib/latinum/bank.rb', line 92

def rates
  @rates
end

#symbolsObject (readonly)

A map of all recognised symbols ordered by priority.



96
97
98
# File 'lib/latinum/bank.rb', line 96

def symbols
  @symbols
end

Instance Method Details

#<<(rate) ⇒ Object

Add an exchange rate to the bank.



104
105
106
107
108
109
# File 'lib/latinum/bank.rb', line 104

def <<(rate)
	@rates << rate
	
	@exchange[rate.input] ||= {}
	@exchange[rate.input][rate.output] = rate
end

#[](name) ⇒ Object

Look up a currency by name.



88
89
90
# File 'lib/latinum/bank.rb', line 88

def [](name)
	@currencies[name]
end

#exchange(resource, for_name) ⇒ Object

Exchange one resource for another using internally specified rates.



112
113
114
115
116
117
118
119
120
# File 'lib/latinum/bank.rb', line 112

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(resource, *arguments, **options) ⇒ Object

Format a resource as a string according to the loaded currencies.



155
156
157
158
159
160
161
# File 'lib/latinum/bank.rb', line 155

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

#from_integral(amount, name) ⇒ Object

Convert the resource from an integral representation based on the currency’s precision.



176
177
178
179
180
# File 'lib/latinum/bank.rb', line 176

def from_integral(amount, name)
	formatter = @formatters[name]
	
	Resource.new(formatter.from_integral(amount), name)
end

#import(resources) ⇒ Object

Import a list of resource templates, e.g. currencies.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/latinum/bank.rb', line 70

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

#parse(string, default_name: nil) ⇒ Object

Parse a string according to the loaded currencies.



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/latinum/bank.rb', line 123

def parse(string, default_name: nil)
	parts = string.strip.split(/\s+/, 2)
	
	if parts.size == 2
		return Resource.new(parts[0].gsub(/[^\-\.0-9]/, ''), parts[1])
	else
		# Lookup the named symbol, e.g. '$', and get the highest priority name:
		symbol = @symbols.fetch(string.gsub(/[\-\.,0-9]/, ''), []).last
		
		if symbol
			return Resource.new(string.gsub(/[^\-\.0-9]/, ''), symbol.last.to_s)
		elsif default_name
			return Resource.new(string.gsub(/[^\-\.0-9]/, ''), default_name.to_s)
		else
			raise ArgumentError.new("Could not parse #{string}, could not determine currency!")
		end
	end
end

#round(resource) ⇒ Object

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.



145
146
147
148
149
150
151
# File 'lib/latinum/bank.rb', line 145

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

#to_integral(resource) ⇒ Object

Convert the resource to an integral representation based on the currency’s precision.



166
167
168
169
170
# File 'lib/latinum/bank.rb', line 166

def to_integral(resource)
	formatter = @formatters[resource.name]
	
	formatter.to_integral(resource.amount)
end