2010-09-27 7 views
1

J'ai trouvé ce module pour la gemme Money qui se met à jour auprès de la BCE Banque Centrale Européenne (met à jour ses tarifs toutes les 24 heures) mais je ne sais pas comment je devrais faire de la mise en cache dans mon rails application qui utilise plusieurs devises.rails caching with money gem (eu_central_bank)

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 

Il a une fonction d'écrire les tarifs à certains fichiers ... mais je ne suis pas sûr que ce soit ce que je veux. J'utilise aussi heroku qui a un système de fichiers en lecture seule.

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

Je ne trouvais aucun moyen de vérifier l'âge de l'objet non plus. Je me demandais juste la meilleure option pour le charger une fois par 24 heures et persister pour toute mon application Rails. Des pointeurs?

+0

salut, je suis l'auteur de eu_central_bank.Serait-il bon si j'ajoute une méthode pour obtenir la date des taux? comme "eu_bank.updated_date" et il vous renvoie la date du taux. si ça sonne bien, les pls le soulèvent comme un problème à github. Je vais alors y arriver. – liangzan

Répondre

0

Étant donné que la quantité de données est relativement faible, vous pouvez stocker l'objet eu_bank dans la mémoire avec une date d'expiration de 24 heures (voir expiration dans this doc).

Et chaque fois que vous en avez besoin, vous le récupérez dans memchache et Marshal.load.

Si la clé a expiré ou disparu du cache, vous allez chercher à nouveau pour de vrai

0

Ma solution actuelle est pas très élégant, mais travaille en ce moment - j'utilise initialiseur et taux mise à jour/cache sur début de l'application

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) 
1

Je vient de déployer une solution qui met en cache les taux de change dans memcache et met à jour toutes les 24 heures. Vous devez utiliser la dernière gemme de l'argent, commettre https://github.com/RubyMoney/eu_central_bank/commit/fc6c4a3164ad47747c8abbf5c21df617d2d9e644 est nécessaire. Puisque je ne veux pas redémarrer mes processus Web toutes les 24 heures, je vérifie les nouveaux taux de change dans un before_filter (plus agréable possible?). L'appel Money.default_bank.update_rates réel peut être déplacé dans un travail de resque récurrente (ou autre).

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

J'ai utilisé cette solution dans l'une de mes applications. J'ai juste rencontré un problème: mon code ne pouvait plus trouver la propriété 'last_updated' sur' Money.default_bank.last_updated'. J'ai ajouté 'config.default_bank = EuCentralBank.new' à' initializers/money.rb' et j'ai redémarré mon application. Je pense que cela a à voir avec une mise à jour dans la gemme 'Money', mais je peux me tromper;) – Webdevotion

3

Cela peut être fait en utilisant Rails de mise en cache de bas niveau et un 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 

Ce code téléchargera les taux une fois en 24 heures et sauvegarder les résultats dans le cache (quelle que soit la mise en cache module que vous utilisez), d'où l'objet banque les charge à chaque requête.