如何跨请求记忆哈希?
How to memoize hash across requests?
在我的 Rails 应用程序中,我有一个非常 昂贵的 函数,它每天从外部服务获取一组转换率:
require 'open-uri'
module Currency
def self.all
@all ||= fetch_all
end
def self.get_rate(from_curr = "EUR", to_curr = "USD")
all[from_curr][to_curr]
end
private
def self.fetch_all
hashes = {}
CURRENCIES.keys.each do |currency|
hash = JSON.parse(open(URI("http://api.fixer.io/latest?base=#{currency}")).read)
hashes[currency] = hash["rates"]
end
hashes
end
end
有没有办法存储这个函数的结果(散列)来加快速度?现在,我正在尝试将它存储在一个实例变量 @all
中,这样可以稍微加快它的速度,但是它不会跨请求持久保存。我怎样才能跨请求保存它?
创建一个文件,让我们在初始化程序中使用以下代码说 currency_rates.rb
:
require 'open-uri'
hashes = {}
CURRENCIES.keys.each do |currency|
hashes[currency] = JSON.parse(open(URI("http://api.fixer.io/latest?base=#{currency}")).read)["rates"]
end
CURRENCY_RATES = hashes
然后编写以下每天 运行 的 rake 任务:
task update_currency_rates: :environment do
require 'open-uri'
hashes = {}
CURRENCIES.keys.each do |currency|
hashes[currency] = JSON.parse(open(URI("http://api.fixer.io/latest?base=#{currency}")).read)["rates"]
end
Constant.const_set('CURRENCY_RATES', hashes)
end
唯一的缺点是每次部署新版本 app/on 时它都会 运行 重新启动。觉得可以的话可以去
如果你使用像 memcachier
之类的缓存,你可以避免这种情况,然后你可以这样做,
def currency_rates
Rails.cache.fetch('currency_rates', expires_in: 24.hours) do
# write above code in some method and call here which will return hash and thus it will be cached.
end
end
我会像这样懒惰地初始化散列:
require 'open-uri'
require 'json'
module Currency
def self.get_rate(from_curr = "EUR", to_curr = "USD")
@memorized_result ||={}
@memorized_result.fetch(from_curr) do |not_found_key|
data = JSON.parse(open(URI("http://api.fixer.io/latest?base=# {not_found_key}")).read)
@memorized_result[not_found_key] = data["rates"]
end[to_curr]
end
end
我认为您不需要一直都需要所有的汇率。因此,您可以通过一次只获取所需的一个来加快速度。随着时间的推移,您会将所有费率保存在内存中。
在某些极端情况下,这会在请求之间持续存在。这取决于您的服务器,例如,独角兽使用多个进程。每个进程都有自己的
@memorized_result
变量,需要填写
如果你想在多个进程或服务器之间共享这些数据,那么你需要一个存储空间来存储可以在多个进程之间共享的数据。
如果您的条目需要生命周期,那么我会调整@Md。 Farhan Memon Rails 缓存提示如下:
def get_rate(from_curr = "EUR", to_curr = "USD")
Rails.cache.fetch("currency_rates_#{from_curr}_#{to_curr}", expires_in: 24.hours) do
data = JSON.parse(open(URI("http://api.fixer.io/latest?base=#{from_curr}")).read)
data["rates"][to_curr]
end
end
在我的 Rails 应用程序中,我有一个非常 昂贵的 函数,它每天从外部服务获取一组转换率:
require 'open-uri'
module Currency
def self.all
@all ||= fetch_all
end
def self.get_rate(from_curr = "EUR", to_curr = "USD")
all[from_curr][to_curr]
end
private
def self.fetch_all
hashes = {}
CURRENCIES.keys.each do |currency|
hash = JSON.parse(open(URI("http://api.fixer.io/latest?base=#{currency}")).read)
hashes[currency] = hash["rates"]
end
hashes
end
end
有没有办法存储这个函数的结果(散列)来加快速度?现在,我正在尝试将它存储在一个实例变量 @all
中,这样可以稍微加快它的速度,但是它不会跨请求持久保存。我怎样才能跨请求保存它?
创建一个文件,让我们在初始化程序中使用以下代码说 currency_rates.rb
:
require 'open-uri'
hashes = {}
CURRENCIES.keys.each do |currency|
hashes[currency] = JSON.parse(open(URI("http://api.fixer.io/latest?base=#{currency}")).read)["rates"]
end
CURRENCY_RATES = hashes
然后编写以下每天 运行 的 rake 任务:
task update_currency_rates: :environment do
require 'open-uri'
hashes = {}
CURRENCIES.keys.each do |currency|
hashes[currency] = JSON.parse(open(URI("http://api.fixer.io/latest?base=#{currency}")).read)["rates"]
end
Constant.const_set('CURRENCY_RATES', hashes)
end
唯一的缺点是每次部署新版本 app/on 时它都会 运行 重新启动。觉得可以的话可以去
如果你使用像 memcachier
之类的缓存,你可以避免这种情况,然后你可以这样做,
def currency_rates
Rails.cache.fetch('currency_rates', expires_in: 24.hours) do
# write above code in some method and call here which will return hash and thus it will be cached.
end
end
我会像这样懒惰地初始化散列:
require 'open-uri'
require 'json'
module Currency
def self.get_rate(from_curr = "EUR", to_curr = "USD")
@memorized_result ||={}
@memorized_result.fetch(from_curr) do |not_found_key|
data = JSON.parse(open(URI("http://api.fixer.io/latest?base=# {not_found_key}")).read)
@memorized_result[not_found_key] = data["rates"]
end[to_curr]
end
end
我认为您不需要一直都需要所有的汇率。因此,您可以通过一次只获取所需的一个来加快速度。随着时间的推移,您会将所有费率保存在内存中。
在某些极端情况下,这会在请求之间持续存在。这取决于您的服务器,例如,独角兽使用多个进程。每个进程都有自己的
@memorized_result
变量,需要填写
如果你想在多个进程或服务器之间共享这些数据,那么你需要一个存储空间来存储可以在多个进程之间共享的数据。
如果您的条目需要生命周期,那么我会调整@Md。 Farhan Memon Rails 缓存提示如下:
def get_rate(from_curr = "EUR", to_curr = "USD")
Rails.cache.fetch("currency_rates_#{from_curr}_#{to_curr}", expires_in: 24.hours) do
data = JSON.parse(open(URI("http://api.fixer.io/latest?base=#{from_curr}")).read)
data["rates"][to_curr]
end
end