кэширование рельсов с помощью самоцвета (eu_central_bank) - PullRequest
1 голос
/ 27 сентября 2010

Я нашел это дополнение для драгоценного камня Money, которое обновляется Европейским центральным банком ЕЦБ (обновляет его ставки каждые 24 часа), но я не уверен, как мне следует кэшировать в моем приложении rails, которое использует несколько валют. 1001 *

http://github.com/RubyMoney/eu_central_bank

eu_bank ||= EuCentralBank.new
eu_bank.update_rates
#Rails.cache.fetch('rates', :expires_in => 24.hours) { eu_bank.update_rates }
rate = eu_bank.exchange_with(Money.new(100, session[:currency]), "USD").to_f

У него есть функция для записи ставок в какой-то файл ... но я тоже не уверен, что это то, чего я хочу. Я также использую heroku, который имеет файловую систему только для чтения.

eu_bank.save_rates("/some/file/location/exchange_rates.xml")

Я также не смог найти способ проверить возраст на объекте. Мне просто интересно, как лучше загрузить его раз в 24 часа и сохранить для всего моего приложения Rails. Есть указатели?

Ответы [ 4 ]

4 голосов
/ 26 февраля 2014

Это можно сделать с помощью низкоуровневого кэширования Rails и фильтра before_filter:

class ApplicationController < ActionController::Base

  before_filter :set_conversion_rates

  def set_conversion_rates

    rates = Rails.cache.fetch "money:eu_central_bank_rates", expires_in: 24.hours do

      Money.default_bank.save_rates_to_s
    end

    Money.default_bank.update_rates_from_s rates

  end
end

Этот код будет загружать скорости один раз в 24 часа и сохранять результаты в кэш (независимо от используемого модуля кэширования), откуда объект банка загружает их по каждому запросу.

1 голос
/ 01 июня 2012

Я только что развернул решение, которое кэширует обменные курсы в memcache и обновляет его каждые 24 часа.Вы должны использовать последний драгоценный камень, необходимо совершить https://github.com/RubyMoney/eu_central_bank/commit/fc6c4a3164ad47747c8abbf5c21df617d2d9e644.Поскольку я не хочу перезапускать свои веб-процессы каждые 24 часа, я проверяю новые обменные курсы в before_filter (более хороший способ?).Фактический вызов Money.default_bank.update_rates может быть перемещен в повторяющееся задание (или что-то еще).

lib / my_namespace / bank.rb

module MyNamespace
  class Bank
    def self.update_rates_if_changed
      if last_updated.nil? || last_updated + 12.hours <= Time.now
        update_rates
      end
    end

    def self.update_rates
      fetch_rates

      # Take latest available currency rates snapshot
      [0, 1, 2].each do |days|
        date = Date.today - days.days
        next unless Rails.cache.exist?(rate_key(date))

        begin
          rates = Rails.cache.read(rate_key(date))
          Money.default_bank.update_rates_from_s(rates)
        rescue Nokogiri::XML::SyntaxError
          print "error occurred while reading currency rates"
          # our rates seem to be invalid, so clear the cache and retry
          Rails.cache.delete(rate_key(date))
          update_rates
        end

        break
      end
    end

    private
    def self.fetch_rates
      return if Rails.cache.exist?(rate_key)

      print "Updating currency rates ... "
      begin
        Rails.cache.write(rate_key, Money.default_bank.save_rates_to_s)
        puts "finished"
      rescue Exception => ex
        puts "error occurred: #{ex.inspect}"
      end
    end

    def self.rate_key(date = Date.today)
      ["exchange_rates", date.strftime("%Y%m%d")]
    end

    def self.last_updated
      Money.default_bank.last_updated
    end
  end
end

app / controllers / application_controller.rb

class ApplicationController
  before_filter :check_for_currency_updates

  def check_for_currency_updates
    MyNamespace::Bank.update_rates_if_changed
  end
end

config / initializers / money.rb

MyNamespace::Bank.update_rates_if_changed
0 голосов
/ 16 июля 2011

Мое текущее решение не очень элегантно, но работает в данный момент - я использую инициализатор и частоту обновления / кэширования при запуске приложения.

config / initializers / money.rb

# Money exchange
::Money.default_bank = ::EuCentralBank.new

EU_CENTRAL_BANK_CACHE = '/tmp/eu_bank_exchange_rates.xml'

# Right now we update exchange rates on app restart. App is restarted daily after logs rotation,
# Should be ok for now.

if (!File.exist?(EU_CENTRAL_BANK_CACHE)) || File.mtime(EU_CENTRAL_BANK_CACHE) < 23.hours.ago
  p "Updating money exchange rates"
  ::Money.default_bank.save_rates(EU_CENTRAL_BANK_CACHE)
end

::Money.default_bank.update_rates(EU_CENTRAL_BANK_CACHE)
0 голосов
/ 27 сентября 2010

Поскольку объем данных относительно невелик, вы можете Marshal.dump объект eu_bank, сохранить его в memchache с датой истечения 24 часа (см. Срок действия в в этом документе ) .

И каждый раз, когда вам это нужно, вы извлекаете его из memchache и Marshal.load его.

Если ключ истек или исчез из кеша, вы извлекаете его снова для реального

...