Class: Money::Bank::VariableExchange
- Defined in:
- lib/money/bank/variable_exchange.rb
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_'.freeze
- 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, &block) ⇒ Object
-
#exchange_with(from, to_currency) {|n| ... } ⇒ Money
Exchanges the given
Money
object to a newMoney
object 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, s, opts = {}) ⇒ self
Loads rates provided in
s
given the specified format. -
#initialize(st = Money::RatesStore::Memory.new) {|n| ... } ⇒ VariableExchange
constructor
Initializes a new
Money::Bank::VariableExchange
object. - #marshal_dump ⇒ Object
- #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(st = 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.
59 60 61 62 |
# File 'lib/money/bank/variable_exchange.rb', line 59 def initialize(st = Money::RatesStore::Memory.new, &block) @store = st super(&block) end |
Instance Attribute Details
#mutex ⇒ Object (readonly)
Returns the value of attribute mutex.
45 46 47 |
# File 'lib/money/bank/variable_exchange.rb', line 45 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
158 159 160 |
# File 'lib/money/bank/variable_exchange.rb', line 158 def add_rate(from, to, rate) set_rate(from, to, rate) end |
#calculate_fractional(from, to_currency) ⇒ Object
127 128 129 130 131 132 |
# File 'lib/money/bank/variable_exchange.rb', line 127 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, &block) ⇒ Object
134 135 136 137 138 139 140 141 142 143 |
# File 'lib/money/bank/variable_exchange.rb', line 134 def exchange(fractional, rate, &block) 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
.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/money/bank/variable_exchange.rb', line 109 def exchange_with(from, to_currency, &block) to_currency = Currency.wrap(to_currency) if from.currency == to_currency from else if rate = get_rate(from.currency, to_currency) fractional = calculate_fractional(from, to_currency) from.dup_with( fractional: exchange(fractional, rate, &block), currency: to_currency, bank: self ) else raise UnknownRate, "No conversion rate known for '#{from.currency.iso_code}' -> '#{to_currency}'" end 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
.
221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/money/bank/variable_exchange.rb', line 221 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.open(file, "w") {|f| f.write(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
198 199 200 |
# File 'lib/money/bank/variable_exchange.rb', line 198 def get_rate(from, to, opts = {}) store.get_rate(Currency.wrap(from).iso_code, Currency.wrap(to).iso_code) end |
#import_rates(format, s, opts = {}) ⇒ self
Loads rates provided in s
given the specified format. Available formats are :json
, :ruby
and :yaml
. Delegates to Money::RatesStore::Memory
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/money/bank/variable_exchange.rb', line 261 def import_rates(format, s, 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(s) data.each do |key, rate| from, to = key.split(SERIALIZER_SEPARATOR) store.add_rate from, to, rate end end self end |
#marshal_dump ⇒ Object
68 69 70 |
# File 'lib/money/bank/variable_exchange.rb', line 68 def marshal_dump [store.marshal_dump, @rounding_method] end |
#marshal_load(arr) ⇒ Object
72 73 74 75 76 |
# File 'lib/money/bank/variable_exchange.rb', line 72 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.
236 237 238 239 240 |
# File 'lib/money/bank/variable_exchange.rb', line 236 def rates store.each_rate.each_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
177 178 179 |
# File 'lib/money/bank/variable_exchange.rb', line 177 def set_rate(from, to, rate, opts = {}) store.add_rate(Currency.wrap(from).iso_code, Currency.wrap(to).iso_code, rate) end |
#store ⇒ Object
64 65 66 |
# File 'lib/money/bank/variable_exchange.rb', line 64 def store @store.is_a?(String) ? Object.const_get(@store) : @store end |