ruby-on-railscachingmemcacheddalli

Ruby on Rails caching with memcache and Dalli doesn't seem to work


so I implemented some caching on my page that runs on rails 3.3 but when I look into the production log I see this:

Read fragment views/#<Job:0xbbb6970>_big_2 (0.8ms)
Write fragment views/#<Job:0xbbb6970>_big_2 (0.5ms)
Read fragment views/#<Job:0xbbb65d8>_big_2 (0.5ms)
Write fragment views/#<Job:0xbbb65d8>_big_2 (0.6ms)
Read fragment views/#<Job:0xbbb61b4>_big_2 (0.6ms)
Write fragment views/#<Job:0xbbb61b4>_big_2 (0.4ms)
Rendered shared/_jobslist.html.erb (88.5ms)

I am not sure this is supposed to be like this :) As far as I understand it, it should read all the time once the fragment is saved in cache. I specified an expiration of 30 minutes.

<% jobs.each_with_index do |job, i| %>                                         
    <% cache("#{job}_big_2", :expires => 30.minutes) do %>
       ...

Solution

  • Your cache key is the problem (the first argument to #cache). You're telling Rails to identify the cached fragments using the string "#{job}_big_2". To interpolate a Job instance into that string, Ruby will call #to_s on it, resulting in the #<Job:0xbbb61b4> segments you see. But this contains the object_id, which will be different each time the record is loaded - this is why you're not getting any cache hits.

    If Job is a descendant of ActiveRecord::Base, you can use the #cache_key method, which will produce a string with the record's record ID and updated_at timestamp to produce a key that is unique to that record, but which will be regenerated if the record is updated:

    <% jobs.each_with_index do |job, i| %>                                         
        <% cache("#{job.cache_key}_big_2", :expires => 30.minutes) do %>
           ...
    
    Read fragment views/jobs/1234-20130614084704_big_2 (0.8ms)
    ...
    

    If Job is not an AR::Base model then you need to implement a similar method to generate a cache key that will uniquely identify your Job records.