ruby-on-railsrubymemcachednokogiridalli

How to cache Weather (Nokogiri::XML::NodeSet object) in Memcache?


I'm trying to cache Weatherman's response (https://github.com/dlt/yahoo_weatherman) in Memcache to avoid fetching weather multiple times, I am doing:

  weather = Rails.cache.fetch([:weather_by_woeid, weather.woeid], expires_in: 1.hour) do
    client = Weatherman::Client.new
    client.lookup_by_woeid weather.woeid
  end

However I am getting this exception:

ERROR -- : Marshalling error for key 'Timeline:weather_by_woeid/26352062': no _dump_data is defined for class Nokogiri::XML::NodeSet
ERROR -- : You are trying to cache a Ruby object which cannot be serialized to memcached.
ERROR -- : /var/lib/gems/2.2.0/gems/dalli-2.7.4/lib/dalli/server.rb:402:in `dump'

What is the best way to handle this?


Solution

  • This is not possible with the given code base of yahoo_weatherman gem.

    The reason is that Response of the yahoo_weatherman gem encapsulates the XML response in the form of a Nokogiri::XML::NodeSet, which cannot be serialized, and hence cannot be cached.

    To circumvent this problem, we can monkey-patch the Weathernan::Client class so that we get access to raw response of Weatherman API, which is a string and can be cached.

    # Extends the default implementation by a method that can give us raw response
    class Weatherman::Client
        def lookup_raw_by_woeid(woeid)
            raw = get request_url(woeid)
        end
    end
    
    # We call the lookup_raw_by_woeid and cache its response (string)
    weather = Rails.cache.fetch([:weather_by_woeid, weather.woeid], expires_in: 1.hour) do
        client = Weatherman::Client.new
        client.lookup_raw_by_woeid weather.woeid
    end
    
    # We now convert that string into a Weatherman response.
    w = Weatherman::Response.new(weather)
    
    # Print some values from weather response
    p w.wind