Можно ли автоматически получить компоненты ключа кеша в рельсах? - PullRequest
2 голосов
/ 02 апреля 2009

При создании кеш-ключей для визуализируемого контента в веб-приложениях необходимо учитывать все переменные, которые могут изменить результат.
В динамических средах, таких как рельсы, они могут быть определены в разных местах: контроллер, модель, сеанс или серверная среда. И на них можно ссылаться в шаблоне, в шаблоне, отображаемом в шаблоне или в помощнике. Можете ли вы придумать способ автоматического создания списка переменных, которые вносят вклад в содержимое отображаемого шаблона, возможно, используя ParseTree ?

1 Ответ

0 голосов
/ 09 февраля 2011

Я использую «ключ свежести» в моих ключах кеша, вероятно, узнал из этой статьи: http://blog.leetsoft.com/2007/5/22/the-secret-to-memcached

Это позволяет мне легко аннулировать весь кеш, связанный с ресурсом, независимо от URL, несмотря на тот факт, что memcached не предоставляет средства для итерации существующих ключей.

Я обычно генерирую мой, используя комбинацию request.url и идентификатора зарегистрированного пользователя и freshness_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 -%>

Обычно у меня есть наблюдатель для модели коллекции:

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

Надеюсь, это поможет

...