Rails 缓存与 Money gem (eu_central_bank)

发布于 2024-09-25 13:50:23 字数 682 浏览 2 评论 0原文

我发现了 Money gem 的这个附加组件,它从 ECB 欧洲中央银行更新(每 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 应用程序的最佳选择。有什么指点吗?

I found this add-on for the Money gem which updates from the ECB European Central Bank (updates its rates every 24 hours) but I'm unsure how I should go about caching in my rails app which uses multiple currencies.

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

It has a function to write out the rates to some file... but i'm not sure that's what I want either. I'm also using heroku which has a read-only file system.

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

I couldn't find any way to check the age on the object either. I'm just wondering the best option to load it once per 24 hours and persist for my entire Rails app. Any pointers?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

请持续率性 2024-10-02 13:50:24

我当前的解决方案不是很优雅,但目前有效 - 我在应用程序启动时使用初始化程序和更新/缓存速率。

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)

My current solution is not very elegant, but works at the moment - I'm using initializer and update/cache rates on app start.

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)
ぃ双果 2024-10-02 13:50:24

我刚刚部署了一个解决方案,将汇率缓存在 memcache 中并每 24 小时更新一次。你必须使用最新的金钱宝石,提交 https://github.com/RubyMoney/eu_central_bank/commit /fc6c4a3164ad47747c8abbf5c21df617d2d9e644 是必需的。由于我不想每 24 小时重新启动一次 Web 进程,因此我在 before_filter 中检查新的汇率(可能有更好的方法吗?)。实际的 Money.default_bank.update_rates 调用可能会移至重复的 resque 作业(或其他作业)中。

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

应用程序/控制器/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

I just deployed a solution that caches the exchange rates in memcache and updates it every 24 hours. You have to use the latest money gem, commit https://github.com/RubyMoney/eu_central_bank/commit/fc6c4a3164ad47747c8abbf5c21df617d2d9e644 is required. Since I don't want to restart my web processes every 24 hours, I check for new exchange rates in a before_filter (nicer way possible?). The actual Money.default_bank.update_rates call might be moved into a recurring resque job (or whatever).

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
泅人 2024-10-02 13:50:24

由于数据量相对较小,您可以 Marshal.dump eu_bank 对象,将其存储在 memchache 中,有效期为 24 小时(请参阅此文档中的过期时间)。

每次你需要它时,你都可以从 memchache 和 Marshal.load 中检索它。

如果密钥已过期或从缓存中消失,您将再次真正获取它

Since the amount of data is relatively small you can Marshal.dump the eu_bank object, store it in memchache with an expiry date of 24 hours (see expiration in this doc).

And each time you need it you retrieve it from memchache and Marshal.load it.

If the key has expired or vanished from the cache, you fetch it again for real

腹黑女流氓 2024-10-02 13:50:23

这可以通过使用 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 小时下载一次汇率,并将结果保存到缓存(无论您使用什么缓存模块),银行对象会在每次请求时从其中加载它们。

This can be done by using Rails low-level caching and a 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

This code will download the rates once in 24 hours and save the results to the cache (whatever caching module you use), from where the bank object loads them on every request.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文