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 collapse

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 Attribute Details

#ratesObject (readonly)

Returns the value of attribute rates.



33
34
35
# File 'lib/money/bank/variable_exchange.rb', line 33

def rates
  @rates
end

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:

Returns:



122
123
124
# File 'lib/money/bank/variable_exchange.rb', line 122

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:

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.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/money/bank/variable_exchange.rb', line 87

def exchange_with(from, to_currency)
  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 = BigDecimal.new(from.cents.to_s) / (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?
         yield 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.



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/money/bank/variable_exchange.rb', line 180

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:



158
159
160
# File 'lib/money/bank/variable_exchange.rb', line 158

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.



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/money/bank/variable_exchange.rb', line 219

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

#marshal_dumpObject



47
48
49
# File 'lib/money/bank/variable_exchange.rb', line 47

def marshal_dump
  [@rates, @rounding_method]
end

#marshal_load(arr) ⇒ Object



51
52
53
54
# File 'lib/money/bank/variable_exchange.rb', line 51

def marshal_load(arr)
  @rates, @rounding_method = arr
  @mutex = Mutex.new
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:

Returns:



139
140
141
# File 'lib/money/bank/variable_exchange.rb', line 139

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)


41
42
43
44
45
# File 'lib/money/bank/variable_exchange.rb', line 41

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