是否可以在rails中自动派生缓存键的组件?

时间:2009-04-02 17:18:56

标签: ruby-on-rails model-view-controller caching introspection fragment-caching

在Web应用程序中为渲染内容生成缓存键时,必须考虑可能会更改结果的所有变量。
在像rails这样的动态环境中,可以在不同的地方定义它们:控制器,模型,会话或服务器环境。它们可以在模板中,模板中呈现的模板或帮助器中引用。 您能想到一种方法来自动生成有助于渲染模板内容的变量列表,可能使用ParseTree吗?

1 个答案:

答案 0 :(得分:0)

我在缓存键中使用了“新鲜度密钥”,可能是从这篇文章中学到的:   http://blog.leetsoft.com/2007/5/22/the-secret-to-memcached

这使得我可以轻松地使与资源相关的所有缓存无效,无论url如何,尽管memcached不提供迭代现有密钥的工具。

我通常使用request.url和登录用户ID以及fresh_key的组合生成我的,例如

# 
# return the freshness_key for caching this particular collection
def get_freshness_key_for(collection_name)
  Rails.cache.fetch("#{self.id}:#{collection_name}") { "#{self.send(collection_name).maximum(:updated_at).to_i}:#{Time.now.to_i}" }
end

# 
# set the freshness_key for caching this particular collection;
# typically called after_save from an Observer for this collection
# 
def set_freshness_key_for(collection_name)
  Rails.cache.write("#{self.id}:#{collection_name}", "#{self.send(collection_name).maximum(:updated_at).to_i}:#{Time.now.to_i}")
end

# returns the cache_key for this client, the desired collection, and the
# current url with the latest freshness_key
# 
# the url is hashed so as not to overrun memcached's key length limit
def cache_key_for(collection_name, request_url)
  freshness_key = self.get_freshness_key_for(collection_name)
  "#{self.id}:#{Digest::MD5.hexdigest(request_url)}:#{freshness_key}"
end

我将在控制器中使用它:

@posts_cache_key = cache_key_for(:posts)

@posts = cache(@posts_cache_key) do
  Post.paginate(
    :page => params[:page],
    :per_page => params[:pp]
  )
end

......并且在视图中:

<% cache(:key => "#{@posts_cache_key}:posts_list_fragment") do -%>
  ... html here ...
<% end -%>

通常我会为集合模型提供一个Observer:

class PostObserver < ActiveRecord::Observer

  def after_save(post)
    post.client.set_freshness_key_for(:posts)
  end

  def after_destroy(post)
    post.client.set_freshness_key_for(:posts)
  end

end

希望这有帮助