1

我正在使用这里描述的 Rails 的新缓存解决方案。

开发环境工作正常,但测试生产发送无效ETag标头忽略stale?函数的参数。

这是我的一个控制器的相应部分:

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

stale?方法ActionController::Base调用fresh_when设置对象的方法etagResponse其代码如下:

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

如果我在每个环境中都得到它,模型Category就会发送正确的:cache_key

>> 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"

所以我根本不明白发生了什么,因为当我http://localhost:3000/admin/categories/开发环境中选择 URL 时,ETag每次保存时都会发生变化,Category但在测试生产中却没有。

我已经用webrickThin测试过了

4

2 回答 2

2

解决方案是该Category.all方法在类级别缓存结果,因此一旦获取它,所有内容都会为其余请求缓存。

它在开发环境中不存在,因为每次重新加载模型时,因为在那个环境config.cache_classesfalse

于 2010-01-18T16:05:41.510 回答
0

我不知道标题行/参数是否有最大值,但是对于很多类别,ETag 值会变得很长,正如您的示例已经显示的那样。

您可以找到最新的修改日期并将其用于 ETag,而不是创建一个包含所有创建/修改日期的大字符串。

此外,您引用的文章使用fresh?而不是stale?包含其他一些方法。你为什么不使用那些?

编辑:在查看更新链接中的文章时,解决方案似乎是,只需填写一个@category(与他们一样)。因此找到最后修改的类别

@category = Category.find(:first, :order => 'date DESC')

并使用此值生成 ETag 的 MD5。仅在呈现页面时
获取完整列表。@categories

于 2010-01-17T17:30:52.797 回答