'Why won't Rails.cache store API responses?

I am trying to cache the results of API calls. My application makes multiple calls with the same result and I would like it to use the cache to save time. When I use Rails.cache.fetch the block of code (with the API request) is executed every time even though the keys are the same. I have enabled caching in the development environment using rails dev:cache.

I tried to test in the rails console but my local rails console also won't store any keys in the cache. On heroku, the console works for caching but the application still sends every API request.

I have tried to use both memory and file-based caching locally.

Here is the method in application_record.rb

I am removing the parameters that are not consistent or important for my purpose and then using the parameters and path as the cache key.

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  def send_request(params,path)
    key = params.except(:token, :start_date, :end_date)
    key[:path] = path
    puts key.to_s
    Rails.cache.fetch(key, expires_in: 5.minutes) do
      if (!$token || $token == '') then self.authenticate end
      params[:token] = $token
      url = URI("https://<api-domain>/"+path+"/?"+params.to_query)
      puts '**** sending request *****'
      begin
        Net::HTTP.start(url.host, url.port, :use_ssl => url.scheme == 'https') do |http|
          request = Net::HTTP::Get.new(url)
          request["cache-control"] = 'no-cache'
          response = http.request(request)
          if response.code == "200"
            return response
          elsif response.code[0] == "4"
            puts "recursive = "+response.code
            puts response.read_body
            $token = nil
            send_request(params,path)
          else
            puts "request_report server error"
            puts response.code
            puts JSON.parse(response.read_body)
            response
          end
        end
      rescue
        response = "SocketError: check that the server allows outbound https and that the bucksense API is live"
      end
    end
  end

The log shows that requests are made every time. The first and second requests for both of these campaigns are exactly the same.

Entering new campaign: Show********************************
{:metrics=>"wins,win_rate,ctr,clicks_global", :timezone=>"UTC", :type=>"1", :method=>"getdata", :groupby=>"P1D", :dimensions=>"advertiser_name,campaign_name", :path=>"3.0/report/thirdpart"}
**** sending request *****
{:metrics=>"wins,win_rate,ctr,clicks_global", :timezone=>"UTC", :type=>"1", :method=>"getdata", :groupby=>"P1M", :dimensions=>"advertiser_name,campaign_name", :path=>"3.0/report/thirdpart"}
**** sending request *****
Campaign finished: ********************************



Entering new campaign: ********************************
{:metrics=>"wins,win_rate,ctr,clicks_global", :timezone=>"UTC", :type=>"1", :method=>"getdata", :groupby=>"P1D", :dimensions=>"advertiser_name,campaign_name", :path=>"3.0/report/thirdpart"}
**** sending request *****
{:metrics=>"wins,win_rate,ctr,clicks_global", :timezone=>"UTC", :type=>"1", :method=>"getdata", :groupby=>"P1M", :dimensions=>"advertiser_name,campaign_name", :path=>"3.0/report/thirdpart"}
**** sending request *****
Campaign finished: ********************************

I expect this to make API calls only when the same request has not been made within 5 minutes. Instead, it makes the API call every single time.

Thanks for the help, let me know if I'm making a stupid mistake, or if this is a poor way to achieve my desired results.



Solution 1:[1]

HTTP::Response objects are not serializable, so they can't be stored in the cache. (See this Rails comment.)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1