Ruby on rails 将.xml文件包含到rails并使用它

Ruby on rails 将.xml文件包含到rails并使用它,ruby-on-rails,xml,Ruby On Rails,Xml,所以我有一个currency.xml文件: 现在,我想知道,如何让我的rails应用程序读取它?我甚至必须把它放在哪里,如何包括它? 我基本上是在做一个货币汇率计算器 我将使下拉菜单中的.xml表中的货币名称显示在其中并可用。首先,您必须能够读取该文件--我假设您需要该站点的最新版本,因此您将发出HTTP请求(否则,只需将文件存储在应用程序中的任何位置,并使用file.read和相对路径读取即可)。这里我使用Net::HTTP,但您可以使用HTTParty或任何您喜欢的方法 它看起来每天都在变

所以我有一个currency.xml文件:

现在,我想知道,如何让我的rails应用程序读取它?我甚至必须把它放在哪里,如何包括它?
我基本上是在做一个货币汇率计算器


我将使下拉菜单中的.xml表中的货币名称显示在其中并可用。

首先,您必须能够读取该文件--我假设您需要该站点的最新版本,因此您将发出HTTP请求(否则,只需将文件存储在应用程序中的任何位置,并使用
file.read
和相对路径读取即可)。这里我使用
Net::HTTP
,但您可以使用
HTTParty
或任何您喜欢的方法

它看起来每天都在变化,所以您可能只希望每天发出一个HTTP请求,并将文件与时间戳一起缓存到某个位置

假设您的应用程序中有一个名为
rates
的目录,我们在其中存储缓存的xml文件,功能的核心可能是这样的(有点笨重,但我希望其行为是显而易见的):

这里的重要部分是
散列。从_xml
。如果有本质上是键/值对的xml,这就是您的朋友。对于任何更复杂的内容,您都需要查找类似
Nokogiri
的xml库。
[“信封”][“立方体”[“立方体”][“立方体”][“立方体”]
正在挖掘散列以获得重要部分

现在,您可以看到这对XML结构中的任何更改有多敏感,您应该使端点可配置,并且该散列可能足够小,可以缓存在内存中,但这是基本思想

要从散列中获取货币列表,只需说
get\u rates.keys

只要你了解发生了什么,你就可以把它缩小:

def get_rates
  today_path = Rails.root.join 'rates', "#{Date.today.to_s}.xml"

  Hash[Hash.from_xml(if File.exists? today_path
                       File.read today_path
                     else
                       xml = Net::HTTP.get URI 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'
                       File.write today_path, xml
                       xml
                     end)["Envelope"]["Cube"]["Cube"]["Cube"].map &:values]
end
如果您确实选择缓存XML,您可能也希望自动清除缓存的XML文件的旧版本。如果您想缓存其他转换列表,请考虑从URI中自动导出命名方案,例如“代码> EUROFXRIF-DYLY-2013-10-28。 编辑:假设您想在内存中缓存转换后的xml——为什么不呢

现在只要
将CurrencyRetrieval
包含在您需要的任何地方,就可以了。
@@rates
@@rates\u retrieve
将作为类变量存储在包含此模块的任何类中。您必须测试在生产设置中的调用之间是否存在这种情况(否则,返回到基于文件的方法或将这些值存储到其他位置)


注意,如果XML结构发生变化,或者XML现在不可用,您将希望以某种好的方式使
@@rates
无效并处理异常…安全性比抱歉要好。

我现在能用货币列表调用货币吗?我仍在使用您给出的第一个示例,试图研究它:)我的意思是..例如,我能在select标签中使用它吗?目前我在那里有一行:options_for_select(@currency_list,:currency)但这给了我一个错误:nil:NilClass的未定义方法“map”以前从未使用过select_标记,已经习惯了。但其目的是让currencys的名称出现在其中。另外,当您将它们全部放入一个模块中时,为什么需要使用两个@?前缀@会导致变量成为类变量。这意味着它们将l设置在类级别,而不是实例级别。因此,假设您在ApplicationController中
包含CurrencyRetrieval
,这意味着从ApplicationController继承的任何东西的每个实例(可能是您的所有控制器)都将访问同一个缓存列表。我不完全理解您的意思(如果这是在客户端或视图代码中)最好只提出第二个问题。如果您有货币名称到符号的映射,则使用当前选项的文本(而不是值,因为这将是该货币的转换率,例如1.317而不是“美元”)查找该映射应该很简单。在构建该选择时,您可以将其编码为选项上的HTML属性。如果您查找文档,则用于选择的选项非常灵活。
def get_rates
  today_path = Rails.root.join 'rates', "#{Date.today.to_s}.xml"

  Hash[Hash.from_xml(if File.exists? today_path
                       File.read today_path
                     else
                       xml = Net::HTTP.get URI 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'
                       File.write today_path, xml
                       xml
                     end)["Envelope"]["Cube"]["Cube"]["Cube"].map &:values]
end
module CurrencyRetrieval
  def get_rates
    if defined?(@@rates_retrieved) && (@@rates_retrieved == Date.today)
      @@rates
    else
      @@rates_retrieved = Date.today
      @@rates = Hash[Hash.from_xml(Net::HTTP.get URI 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml')["Envelope"]["Cube"]["Cube"]["Cube"].map &:values]
    end
  end
end