Search code examples
ruby-on-railsrubycachingidiomsmemoization

How do I cache a method with Ruby/Rails?


I have an expensive (time-consuming) external request to another web service I need to make, and I'd like to cache it. So I attempted to use this idiom, by putting the following in the application controller:

def get_listings
  cache(:get_listings!)
end

def get_listings!
  return Hpricot.XML(open(xml_feed))
end

When I call get_listings! in my controller everything is cool, but when I call get_listings Rails complains that no block was given. And when I look up that method I see that it does indeed expect a block, and additionally it looks like that method is only for use in views? So I'm guessing that although it wasn't stated, that the example is just pseudocode.

So my question is, how do I cache something like this? I tried various other ways but couldn't figure it out. Thanks!


Solution

  • As nruth suggests, Rails' built-in cache store is probably what you want.

    Try:

    def get_listings
      Rails.cache.fetch(:listings) { get_listings! }
    end
    
    def get_listings!
      Hpricot.XML(open(xml_feed))
    end
    

    fetch() retrieves the cached value for the specified key, or writes the result of the block to the cache if it doesn't exist.

    By default, the Rails cache uses file store, but in a production environment, memcached is the preferred option.

    See section 2 of http://guides.rubyonrails.org/caching_with_rails.html for more details.