кэширование рельсов с помощью денежного камня (eu_central_bank)

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

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. Есть указатели?


person holden    schedule 27.09.2010    source источник
comment
привет, я автор eu_central_bank. Было бы хорошо, если бы я добавил метод для получения даты ставок? например eu_bank.updated_date, и он возвращает вам дату ставки. Если это звучит нормально, пожалуйста, поднимите это как проблему на github. Я тогда займусь этим.   -  person liangzan    schedule 13.08.2011


Ответы (4)


Это можно сделать с помощью низкоуровневого кэширования 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 часа и сохранять результаты в кеш (какой бы модуль кеширования вы ни использовали), откуда объект банка загружает их при каждом запросе.

person Peter Sorowka    schedule 25.02.2014

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

библиотека / 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

приложение / контроллеры / application_controller.rb

class ApplicationController
  before_filter :check_for_currency_updates

  def check_for_currency_updates
    MyNamespace::Bank.update_rates_if_changed
  end
end

конфигурация / инициализаторы / money.rb

MyNamespace::Bank.update_rates_if_changed
person lacco    schedule 01.06.2012
comment
Я использую это решение в одном из своих приложений. У меня просто возникла проблема: мой код больше не мог найти свойство last_updated на Money.default_bank.last_updated. Я добавил config.default_bank = EuCentralBank.new в initializers/money.rb, и мое приложение снова заработало. Думаю, это связано с обновлением гема Money, но могу ошибаться;) - person Webdevotion; 08.10.2013

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

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

Если срок действия ключа истек или он исчез из кеша, вы получите его снова по-настоящему.

person hellvinz    schedule 27.09.2010

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

конфигурация / инициализаторы / 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)
person Laurynas    schedule 16.07.2011