Class: Money::Bank::HistoricalBank

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

Constant Summary collapse

RATE_FORMATS =

Available formats for importing/exporting rates.

[:json, :ruby, :yaml]

Constants included from OpenExchangeRatesLoader

OpenExchangeRatesLoader::HIST_URL, OpenExchangeRatesLoader::OER_URL

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from OpenExchangeRatesLoader

#load_data

Instance Attribute Details

#ratesObject (readonly)

Returns the value of attribute rates.



14
15
16
# File 'lib/money/bank/historical_bank.rb', line 14

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.

    Parameters:

    • from (Money)

      The Money object to exchange.

    • to_currency (Currency, String, Symbol)

      The currency to exchange to.

  • #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.

    Parameters:

    • date (Date)

      The Date at which you want to calculate the rate.

    • 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.



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

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(from.cents.to_s) / (BigDecimal(from.currency.subunit_to_unit.to_s) / BigDecimal(_to_currency_.subunit_to_unit.to_s))

  ex = cents * BigDecimal(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:

  • (String)

Raises:

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



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

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::HistoricalBank.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

Parameters:

  • date (Date)

    Date to retrieve the exchange rate at.

  • from (Currency, String, Symbol)

    Currency to exchange from.

  • to (Currency, String, Symbol)

    Currency to exchange to.

Returns:

  • (Numeric)


61
62
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
# File 'lib/money/bank/historical_bank.rb', line 61

def get_rate(date, from, to)
  @mutex.synchronize do
    unless existing_rates = @rates[date.to_s]
      load_data(date)
      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

Parameters:

  • format (Symbol)

    The format of s.

  • s (String)

    The rates string.

Returns:

  • (self)

Raises:

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



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

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::HistoricalBank.new
bank.set_rate(Date.new(2001, 1, 1), "USD", "CAD", 1.24514)

Parameters:

  • date (Date)

    Date for which the rate is valid.

  • 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:

  • (Numeric)


36
37
38
39
40
# File 'lib/money/bank/historical_bank.rb', line 36

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

#setupObject



18
19
20
21
22
# File 'lib/money/bank/historical_bank.rb', line 18

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