Class: Money::Bank::VariableExchange

Inherits:
Base
  • Object
show all
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.

Examples:

bank = Money::Bank::VariableExchange.new
bank.add_rate("USD", "CAD", 1.24515)
bank.add_rate("CAD", "USD", 0.803115)

c1 = 100_00.to_money("USD")
c2 = 100_00.to_money("CAD")

# Exchange 100 USD to CAD:
bank.exchange_with(c1, "CAD") #=> #<Money @cents=1245150>

# Exchange 100 CAD to USD:
bank.exchange_with(c2, "USD") #=> #<Money @cents=803115>

Constant Summary collapse

RATE_FORMATS =

Available formats for importing/exporting rates.

[:json, :ruby, :yaml]

Instance Attribute Summary

Attributes inherited from Base

#rounding_method

Instance Method Summary collapse

Methods inherited from Base

#initialize, instance, #same_currency?

Constructor Details

This class inherits a constructor from Money::Bank::Base

Instance Method Details

#add_rate(from, to, rate) ⇒ Numeric

Registers a conversion rate and returns it (uses #set_rate).

Examples:

bank = Money::Bank::VariableExchange.new
bank.add_rate("USD", "CAD", 1.24515)
bank.add_rate("CAD", "USD", 0.803115)

Parameters:

  • from (Currency, String, Symbol)

    Currency to exchange from.

  • to (Currency, String, Symbol)

    Currency to exchange to.

  • rate (Numeric)

    Rate to use when exchanging currencies.

Returns:



110
111
112
# File 'lib/money/bank/variable_exchange.rb', line 110

def add_rate(from, to, rate)
  set_rate(from, to, rate)
end

#exchange_with(from, to_currency) {|n| ... } ⇒ Money

Exchanges the given Money object to a new Money object in to_currency.

Examples:

bank = Money::Bank::VariableExchange.new
bank.add_rate("USD", "CAD", 1.24515)
bank.add_rate("CAD", "USD", 0.803115)

c1 = 100_00.to_money("USD")
c2 = 100_00.to_money("CAD")

# Exchange 100 USD to CAD:
bank.exchange_with(c1, "CAD") #=> #<Money @cents=1245150>

# Exchange 100 CAD to USD:
bank.exchange_with(c2, "USD") #=> #<Money @cents=803115>

Parameters:

  • from (Money)

    The Money object to exchange.

  • to_currency (Currency, String, Symbol)

    The currency to exchange to.

Yields:

  • (n)

    Optional block to use when rounding after exchanging one currency for another.

Yield Parameters:

  • n (Float)

    The resulting float after exchanging one currency for another.

Yield Returns:

  • (Integer)

Returns:

Raises:

  • Money::Bank::UnknownRate if the conversion rate is unknown.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/money/bank/variable_exchange.rb', line 75

def exchange_with(from, to_currency, &block)
  return from if same_currency?(from.currency, to_currency)

  rate = get_rate(from.currency, to_currency)
  unless rate
    raise UnknownRate, "No conversion rate known for '#{from.currency.iso_code}' -> '#{to_currency}'"
  end
  _to_currency_  = Currency.wrap(to_currency)

  cents = from.cents / (BigDecimal.new(from.currency.subunit_to_unit.to_s) / BigDecimal.new(_to_currency_.subunit_to_unit.to_s))

  ex = cents * BigDecimal.new(rate.to_s)
  ex = ex.to_f
  ex = if block_given?
         block.call(ex)
       elsif @rounding_method
         @rounding_method.call(ex)
       else
         ex.to_s.to_i
       end
  Money.new(ex, _to_currency_)
end

#export_rates(format, file = nil) ⇒ 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.

Examples:

bank = Money::Bank::VariableExchange.new
bank.set_rate("USD", "CAD", 1.24515)
bank.set_rate("CAD", "USD", 0.803115)

s = bank.export_rates(:json)
s #=> "{\"USD_TO_CAD\":1.24515,\"CAD_TO_USD\":0.803115}"

Parameters:

  • format (Symbol)

    Request format for the resulting string.

  • file (String) (defaults to: nil)

    Optional file location to write the rates to.

Returns:

Raises:

  • Money::Bank::UnknownRateFormat if format is unknown.



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/money/bank/variable_exchange.rb', line 168

def export_rates(format, file=nil)
  raise Money::Bank::UnknownRateFormat unless
    RATE_FORMATS.include? format

  s = ""
  @mutex.synchronize {
    s = case format
        when :json
          JSON.dump(@rates)
        when :ruby
          Marshal.dump(@rates)
        when :yaml
          YAML.dump(@rates)
        end

    unless file.nil?
      File.open(file, "w").write(s)
    end
  }
  s
end

#get_rate(from, to) ⇒ Numeric

Retrieve the rate for the given currencies. Uses Mutex to synchronize data access.

Examples:

bank = Money::Bank::VariableExchange.new
bank.set_rate("USD", "CAD", 1.24515)
bank.set_rate("CAD", "USD", 0.803115)

bank.get_rate("USD", "CAD") #=> 1.24515
bank.get_rate("CAD", "USD") #=> 0.803115

Parameters:

Returns:



146
147
148
# File 'lib/money/bank/variable_exchange.rb', line 146

def get_rate(from, to)
  @mutex.synchronize { @rates[rate_key_for(from, to)] }
end

#import_rates(format, s) ⇒ self

Loads rates provided in s given the specified format. Available formats are :json, :ruby and :yaml.

Examples:

s = "{\"USD_TO_CAD\":1.24515,\"CAD_TO_USD\":0.803115}"
bank = Money::Bank::VariableExchange.new
bank.import_rates(:json, s)

bank.get_rate("USD", "CAD") #=> 1.24515
bank.get_rate("CAD", "USD") #=> 0.803115

Parameters:

  • format (Symbol)

    The format of s.

  • s (String)

    The rates string.

Returns:

  • (self)

Raises:

  • Money::Bank::UnknownRateFormat if format is unknown.



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/money/bank/variable_exchange.rb', line 207

def import_rates(format, s)
  raise Money::Bank::UnknownRateFormat unless
    RATE_FORMATS.include? format

  @mutex.synchronize {
    @rates = case format
             when :json
               JSON.load(s)
             when :ruby
               Marshal.load(s)
             when :yaml
               YAML.load(s)
             end
  }
  self
end

#set_rate(from, to, rate) ⇒ Numeric

Set the rate for the given currencies. Uses Mutex to synchronize data access.

Examples:

bank = Money::Bank::VariableExchange.new
bank.set_rate("USD", "CAD", 1.24515)
bank.set_rate("CAD", "USD", 0.803115)

Parameters:

  • from (Currency, String, Symbol)

    Currency to exchange from.

  • to (Currency, String, Symbol)

    Currency to exchange to.

  • rate (Numeric)

    Rate to use when exchanging currencies.

Returns:



127
128
129
# File 'lib/money/bank/variable_exchange.rb', line 127

def set_rate(from, to, rate)
  @mutex.synchronize { @rates[rate_key_for(from, to)] = rate }
end

#setupself

Setup rates hash and mutex for rates locking

Returns:

  • (self)


39
40
41
42
43
# File 'lib/money/bank/variable_exchange.rb', line 39

def setup
  @rates = {}
  @mutex = Mutex.new
  self
end