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 => @categ开发者_开发百科ories }
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
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
!
I do not know whether there is an maximum on header lines/parameters, but with a lot of categories the ETag value becomes very long, as your example already shows.
Instead of creating a big string containing all creation/modified dates, you could find the latest modification date and use that for an ETag.
Furthermore the article you quoted uses fresh?
instead of stale?
including some other methods. Why are you not using those?
Edit: When looking at the article in your updated link the solution seems to be, to fill in just one @category
(same as they do). Therefore find the last modified category
@category = Category.find(:first, :order => 'date DESC')
and use this value to generate the MD5 for the ETag.
Get the complete list of @categories
only if you are rendering the page.
精彩评论