Search code examples
ruby-on-railshttpcachingetag

bad ETag value in test and production environment


I'm using the new caching solution for Rails as described here.

The development environment works fine, but the test and production sends invalid ETag header ignores the parameter of the stale? function.

Here is is the corresponding part of one of my controllers:

def index
  @categories = Category.all

  if stale?(:etag => @categories)
    respond_to do |format|
      format.html
      format.xml  { render :xml => @categories }
      format.json { render :json => @categories }
    end
  end
end

The stale? method of the ActionController::Base calls the fresh_when method which sets the etag of the Response object, which has the following code:

def etag=(etag)
  if etag.blank?
    headers.delete('ETag')
  else
    headers['ETag'] = %("#{Digest::MD5.hexdigest(ActiveSupport::Cache.expand_cache_key(etag))}")
  end
end

The Category model sends the correct cache_key if I get it in every environment:

>> Category.find(1).cache_key
=> "categories/1-20100117153353"
>> ActiveSupport::Cache.expand_cache_key(Category.find(:all))
=> "categories/1-20100117153353/categories/2-20100117152007/categories/3-20100116094423/categories/4-20100116094423/categories/5-20100116094423/categories/6-20100116094423/categories/7-20100116094423/categories/8-20100117145800/categories/9-20100117145808"

So I simply don't understand what's going on, because when I select the URL http://localhost:3000/admin/categories/ with the development environment, the ETag changes every time when I save on a Category but with test or production it does not.

I've tested it with webrick and thin


Solution

  • the solution was that the Category.all method cached the results on class level, so once it was fetched everything was cached for the rest of the requests.

    it was not there in development environment because every time the model was reloaded because in that environment the config.cache_classes was false!