如何使用Ruby/Rails缓存方法?

Bra*_*iss 11 ruby caching idioms ruby-on-rails memoization

我有一个昂贵的(耗时的)外部请求到我需要做的另一个Web服务,我想缓存它.所以我试图通过将以下内容放在应用程序控制器中来使用这个习惯用法:

def get_listings
  cache(:get_listings!)
end

def get_listings!
  return Hpricot.XML(open(xml_feed))
end
Run Code Online (Sandbox Code Playgroud)

当我get_listings!在我的控制器中调用时,一切都很酷,但是当我调用get_listingsRails时,抱怨没有给出任何阻止​​.当我查找该方法时,我发现它确实期望一个块,另外看起来该方法仅用于视图?所以我猜测虽然没有说明,但这个例子只是伪代码.

所以我的问题是,如何缓存这样的东西?我尝试了其他各种方法,但无法弄明白.谢谢!

nru*_*uth 14

代码内方法看起来像这样:

def get_listings
  @listings ||= get_listings!
end

def get_listings!
  Hpricot.XML(open(xml_feed))
end
Run Code Online (Sandbox Code Playgroud)

它将基于每个请求缓存结果(每个请求的新控制器实例),尽管您可能希望将"memoize"帮助器视为api选项.

如果你想在请求之间共享请不要在类对象上保存数据,因为你的应用程序不是线程安全的,除非你擅长并发编程并确保线程不会干扰彼此对共享的数据访问变量.

跨请求缓存的"rails方式"是Rails.cache存储.Memcached经常使用,但您可能会发现文件或内存存储符合您的需求.这实际上取决于您的部署方式以及是否要优先考虑缓存命中,响应时间,存储(RAM)或使用托管解决方案,例如heroku插件.


Sid*_*ane 9

正如nruth建议的那样,Rails的内置缓存存储可能就是你想要的.

尝试:

def get_listings
  Rails.cache.fetch(:listings) { get_listings! }
end

def get_listings!
  Hpricot.XML(open(xml_feed))
end
Run Code Online (Sandbox Code Playgroud)

fetch()检索指定键的缓存值,或者将块的结果写入缓存(如果它不存在).

默认情况下,Rails缓存使用文件存储,但在生产环境中,memcached是首选选项.

有关详细信息,请参阅http://guides.rubyonrails.org/caching_with_rails.html的第2部分.