Class: Money::Bank::VariableExchange
- Defined in:
- lib/money/bank/variable_exchange.rb,
sig/lib/money/bank/variable_exchange.rbs
Overview
Class for aiding in exchanging money between different currencies. By
default, the Money class uses an object of this class (accessible
through Money#bank) for performing currency exchanges.
By default, Money::Bank::VariableExchange has no knowledge about
conversion rates. One must manually specify them with add_rate, after
which one can perform exchanges with #exchange_with.
Exchange rates are stored in memory using Money::RatesStore::Memory by default.
Pass custom rates stores for other types of storage (file, database, etc)
Constant Summary collapse
- RATE_FORMATS =
Available formats for importing/exporting rates.
[:json, :ruby, :yaml].freeze
- SERIALIZER_SEPARATOR =
"_TO_"- FORMAT_SERIALIZERS =
{ json: JSON, ruby: Marshal, yaml: YAML }.freeze
Instance Attribute Summary collapse
-
#mutex ⇒ Object
readonly
Returns the value of attribute mutex.
Attributes inherited from Base
Instance Method Summary collapse
-
#add_rate(from, to, rate) ⇒ Numeric
Registers a conversion rate and returns it (uses
#set_rate). - #calculate_fractional(from, to_currency) ⇒ Object
- #exchange(fractional, rate) ⇒ void
-
#exchange_with(from, to_currency) {|n| ... } ⇒ Money
Exchanges the given
Moneyobject to a newMoneyobject into_currency. -
#export_rates(format, file = nil, _opts = {}) ⇒ String
Return the known rates as a string in the format specified.
-
#get_rate(from, to, _opts = {}) ⇒ Numeric
Retrieve the rate for the given currencies.
-
#import_rates(format, string, _opts = {}) ⇒ self
Loads rates provided in
stringgiven the specified format. -
#initialize(store = Money::RatesStore::Memory.new) {|n| ... } ⇒ VariableExchange
constructor
Initializes a new
Money::Bank::VariableExchangeobject. - #marshal_dump ⇒ ::Array[untyped]
- #marshal_load(arr) ⇒ Object
-
#rates ⇒ Object
This should be deprecated.
-
#set_rate(from, to, rate, _opts = {}) ⇒ Numeric
Set the rate for the given currencies.
- #store ⇒ Object
Methods inherited from Base
instance, #same_currency?, #setup
Constructor Details
#initialize(store = Money::RatesStore::Memory.new) {|n| ... } ⇒ VariableExchange
Initializes a new Money::Bank::VariableExchange object.
It defaults to using an in-memory, thread safe store instance for
storing exchange rates.
60 61 62 63 |
# File 'lib/money/bank/variable_exchange.rb', line 60 def initialize(store = Money::RatesStore::Memory.new, &) @store = store super(&) end |
Instance Attribute Details
#mutex ⇒ Object (readonly)
Returns the value of attribute mutex.
46 47 48 |
# File 'lib/money/bank/variable_exchange.rb', line 46 def mutex @mutex end |
Instance Method Details
#add_rate(from, to, rate) ⇒ Numeric
Registers a conversion rate and returns it (uses #set_rate).
Delegates to Money::RatesStore::Memory
157 158 159 |
# File 'lib/money/bank/variable_exchange.rb', line 157 def add_rate(from, to, rate) set_rate(from, to, rate) end |
#calculate_fractional(from, to_currency) ⇒ Object
126 127 128 129 130 131 |
# File 'lib/money/bank/variable_exchange.rb', line 126 def calculate_fractional(from, to_currency) BigDecimal(from.fractional.to_s) / ( BigDecimal(from.currency.subunit_to_unit.to_s) / BigDecimal(to_currency.subunit_to_unit.to_s) ) end |
#exchange(fractional, rate) ⇒ void
This method returns an undefined value.
133 134 135 136 137 138 139 140 141 142 |
# File 'lib/money/bank/variable_exchange.rb', line 133 def exchange(fractional, rate, &) ex = fractional * BigDecimal(rate.to_s) if block_given? yield ex elsif @rounding_method @rounding_method.call(ex) else ex end end |
#exchange_with(from, to_currency) {|n| ... } ⇒ Money
Exchanges the given Money object to a new Money object in
to_currency.
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/money/bank/variable_exchange.rb', line 110 def exchange_with(from, to_currency, &) to_currency = Currency.wrap(to_currency) if from.currency == to_currency from elsif (rate = get_rate(from.currency, to_currency)) fractional = calculate_fractional(from, to_currency) from.dup_with( fractional: exchange(fractional, rate, &), currency: to_currency, bank: self, ) else raise UnknownRate, "No conversion rate known for '#{from.currency.iso_code}' -> '#{to_currency}'" end end |
#export_rates(format, file = nil, _opts = {}) ⇒ String
Return the known rates as a string in the format specified. If file
is given will also write the string out to the file specified.
Available formats are :json, :ruby and :yaml.
220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/money/bank/variable_exchange.rb', line 220 def export_rates(format, file = nil, _opts = {}) raise Money::Bank::UnknownRateFormat unless RATE_FORMATS.include?(format) store.transaction do s = FORMAT_SERIALIZERS[format].dump(rates) unless file.nil? File.write(file, s) end s end end |
#get_rate(from, to, _opts = {}) ⇒ Numeric
Retrieve the rate for the given currencies.
data access.
Delegates to Money::RatesStore::Memory
197 198 199 |
# File 'lib/money/bank/variable_exchange.rb', line 197 def get_rate(from, to, _opts = {}) store.get_rate(Currency.wrap(from).iso_code, Currency.wrap(to).iso_code) end |
#import_rates(format, string, _opts = {}) ⇒ self
Loads rates provided in string given the specified format. Available
formats are :json, :ruby and :yaml.
Delegates to Money::RatesStore::Memory
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'lib/money/bank/variable_exchange.rb', line 260 def import_rates(format, string, _opts = {}) raise Money::Bank::UnknownRateFormat unless RATE_FORMATS.include?(format) if format == :ruby warn "[WARNING] Using :ruby format when importing rates is potentially unsafe and " \ "might lead to remote code execution via Marshal.load deserializer. Consider using " \ "safe alternatives such as :json and :yaml." end store.transaction do data = FORMAT_SERIALIZERS[format].load(string) data.each do |key, rate| from, to = key.split(SERIALIZER_SEPARATOR) store.add_rate from, to, rate end end self end |
#marshal_dump ⇒ ::Array[untyped]
69 70 71 |
# File 'lib/money/bank/variable_exchange.rb', line 69 def marshal_dump [store.marshal_dump, @rounding_method] end |
#marshal_load(arr) ⇒ Object
73 74 75 76 77 |
# File 'lib/money/bank/variable_exchange.rb', line 73 def marshal_load(arr) store_info = arr[0] @store = store_info.shift.new(*store_info) @rounding_method = arr[1] end |
#rates ⇒ Object
This should be deprecated.
235 236 237 238 239 |
# File 'lib/money/bank/variable_exchange.rb', line 235 def rates store.each_rate.with_object({}) do |(from, to, rate), hash| hash[[from, to].join(SERIALIZER_SEPARATOR)] = rate end end |
#set_rate(from, to, rate, _opts = {}) ⇒ Numeric
Set the rate for the given currencies.
access.
Delegates to Money::RatesStore::Memory
176 177 178 |
# File 'lib/money/bank/variable_exchange.rb', line 176 def set_rate(from, to, rate, _opts = {}) store.add_rate(Currency.wrap(from).iso_code, Currency.wrap(to).iso_code, rate) end |
#store ⇒ Object
65 66 67 |
# File 'lib/money/bank/variable_exchange.rb', line 65 def store @store.is_a?(String) ? Object.const_get(@store) : @store end |