Class: Money::Bank::ApiBank

Inherits:
Base
  • Object
show all
Includes:
ExchangeRatesLoader
Defined in:
lib/money/bank/api_bank.rb

Constant Summary collapse

RATE_FORMATS =

Available formats for importing/exporting rates.

[:json, :ruby, :yaml]

Constants included from ExchangeRatesLoader

ExchangeRatesLoader::API_URL

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ExchangeRatesLoader

#load_data

Instance Attribute Details

#ratesObject (readonly)

Returns the value of attribute rates.



16
17
18
# File 'lib/money/bank/api_bank.rb', line 16

def rates
  @rates
end

Instance Method Details

#exchange_with(from, to_currency) ⇒ Money #exchange_with(date, from, to_currency) ⇒ Money

Examples:

bank = Money::Bank::VariableExchange.new
bank.add_rate(Date.today, "USD", "CAD", 1.24515)
bank.add_rate(Date.new(2011,1,1), "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(Date.new(2011,1,1), c2, "USD") #=> #<Money @cents=803115>

Overloads:

  • #exchange_with(from, to_currency) ⇒ Money

    Exchanges the given Money object to a new Money object in to_currency. The exchange rate used will be for Date.today. If no rates are here for Date.today, it will try to load them.

  • #exchange_with(date, from, to_currency) ⇒ Money

    Exchanges the Money object from to a new Money object in to_currency, using the exchange rate available on date.

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)

Raises:

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



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/money/bank/api_bank.rb', line 138

def exchange_with(*args)
  date, from, to_currency = args.length == 2 ? [Date.today] + args : args

  return from if same_currency?(from.currency, to_currency)

  rate = get_rate(date, from.currency, to_currency)
  unless rate
    raise UnknownRate, "No conversion rate available for #{date} '#{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}"

Raises:

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



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

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(date, from, to) ⇒ Numeric

Retrieve the rate for the given currencies. Uses Mutex to synchronize data access. If no rates have been set for date, will try to load them using #load_data.

Examples:

bank = Money::Bank::ApiBank.new
d1 = Date.new(2001, 1, 1)
d2 = Date.new(2002, 1, 1)
bank.set_rate(d1, "USD", "CAD", 1.24515)
bank.set_rate(d2, "CAD", "USD", 0.803115)

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


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/money/bank/api_bank.rb', line 63

def get_rate(date, from, to)
  @mutex.synchronize do
    unless existing_rates = @rates[date.to_s]
      load_data(date, from, to)
      existing_rates = @rates[date.to_s]
    end
    rate = nil
    if existing_rates
      rate = existing_rates[rate_key_for(from, to)]
      unless rate
        # Tries to calculate an inverse rate
        inverse_rate = existing_rates[rate_key_for(to, from)]
        rate = 1.0 / inverse_rate if inverse_rate
      end
      unless rate
        # Tries to calculate a pair rate using USD rate
        unless from_base_rate = existing_rates[rate_key_for("USD", from)]
          from_inverse_rate = existing_rates[rate_key_for(from, "USD")]
          from_base_rate = 1.0 / from_inverse_rate if from_inverse_rate
        end
        unless to_base_rate = existing_rates[rate_key_for("USD", to)]
          to_inverse_rate = existing_rates[rate_key_for(to, "USD")]
          to_base_rate = 1.0 / to_inverse_rate if to_inverse_rate
        end
        if to_base_rate && from_base_rate
          rate = to_base_rate / from_base_rate
        end
      end
    end
    rate
  end
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

Raises:

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



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

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(date, from, to, rate) ⇒ Numeric

Set the rate for the given currency pair at a given date. Uses Mutex to synchronize data access.

Examples:

bank = Money::Bank::ApiBank.new
bank.set_rate(Date.new(2001, 1, 1), "USD", "CAD", 1.24514)


38
39
40
41
42
# File 'lib/money/bank/api_bank.rb', line 38

def set_rate(date, from, to, rate)
  @mutex.synchronize do
    internal_set_rate(date, from, to, rate)
  end
end

#setupObject



20
21
22
23
24
# File 'lib/money/bank/api_bank.rb', line 20

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