isthmuses isthmuses - 6 months ago 14
Ruby Question

"You are trying to cache a Ruby object which cannot be serialized to memcached."

I've been having some caching problems with a footer that is shared across multiple sites, and I'm wondering what might be up. Here's the error message and the backtrace:

Cache read: remote_footer_information ({:expires_in=>300 seconds})
Cache generate: remote_footer_information ({:expires_in=>300 seconds})
Cache write: remote_footer_information ({:expires_in=>300 seconds})
Marshalling error for key 'remote_footer_information': no _dump_data is defined for class Proc
You are trying to cache a Ruby object which cannot be serialized to memcached.

/app/vendor/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/server.rb:397:in `dump'
/app/vendor/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/server.rb:397:in `serialize'
/app/vendor/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/server.rb:269:in `set'
/app/vendor/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/server.rb:60:in `request'
/app/vendor/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/options.rb:18:in `block in request'
/app/vendor/ruby-1.9.3/lib/ruby/1.9.1/monitor.rb:211:in `mon_synchronize'
/app/vendor/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/options.rb:17:in `request'
/app/vendor/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/client.rb:348:in `perform'
/app/vendor/bundle/ruby/1.9.1/gems/dalli-2.6.4/lib/dalli/client.rb:199:in `set'
(eval):7:in `block in set_with_newrelic_trace'
...


Here's the place where the cache retrieval is being defined:

require 'httparty'

module Myclassname
class Footer
include HTTParty
format :json
attr_accessor :response

def initialize
@response = Rails.cache.fetch("remote_footer_information", :expires_in => 5.minutes) do
begin
self.class.get("http://www.myappname.net/pages/my_footer.json")
rescue
false
end
end
end

def valid?
unless @response == false || @response.blank?
return @response['footer'] != nil
end

false
end

def footer
unless @response == false || @response.blank?
return @response['footer']
end

nil
end

end
end


And here's the place in the view where this is being called.

<%= yield :footer_legend %>

<div class="clearer"></div>
<div class="divider">
</div>

<% response = Myclassname::Footer.new %>
<% if response && response.valid? %>
<%= response.footer.html_safe %>
<% end %>


What am I doing wrong here? Any ideas would be greatly appreciated. Thanks!

Answer

Apparently the Httparty::Response object returned by Httparty.get is not serializable, which is required to be cached. Try just caching the part of the response that you need, e.g.

response = self.class.get("http://www.myappname.net/pages/my_footer.json")
response['footer'] if response

In fact, the issue it is described here.