Skip to content

Instantly share code, notes, and snippets.

@jeremy
Created December 5, 2012 03:05
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jeremy/4211803 to your computer and use it in GitHub Desktop.
Save jeremy/4211803 to your computer and use it in GitHub Desktop.
Template- and asset-aware ETags

Declared ETags, together with Russian Doll caching, can be used to automatically mix your template and asset versions into the ETags set in your controllers. This avoids the need to blow all browser caches on each deploy and neatly contains the scope of "freshness fallout" when you tweak a view.

To include the template's version in the ETag:

  # Incorporate the cache version for this action into our ETag.
  # This allows template changes to bubble up into HTTP cache
  # freshness and bust browser caches when we make changes.
  etag do
    begin
      CacheDigests::TemplateDigestor.digest(
        "#{controller_name}/#{action_name}",
        request.format.try(:to_sym), lookup_context)
    rescue ActionView::MissingTemplate => e
      '' # Ignore missing templates
    end
  end

Similarly, for your JavaScript and CSS assets:

  ASSET_FRESHNESS_PATHS = %w( application.js application.css )

  # HTML pages cached by the browser should be updated whenever we change
  # our assets, so we include application.css and application.js digests
  # in ETags for HTML pages.
  etag do
    if request.format.try(:html?)
      ASSET_FRESHNESS_PATHS.map { |p| asset_digest_for_etag(p) }.join('-')
    end
  end

  # Check precompiled asset manifest (production) or compute the digest (dev).
  def asset_digest_for_etag(logical_path)
    if manifest = Rails.application.config.assets.digests
      manifest[logical_path]
    else
      Rails.application.assets[logical_path].digest
    end
  end

Coming in Rails 4!

Declared ETags: https://github.com/rails/rails/commit/ed5c938fa36995f06d4917d9543ba78ed506bb8d

Russian Doll caching: https://github.com/rails/cache_digests

Copy link

ghost commented Aug 18, 2013

this is sweet. dumbass question, but where do I plug in this code? An initializer? I tried putting it directly in a controller in my app, but get an "uninitialized constant ControllerName::CacheDigests" error, and don't grok the rails internals enough to figure out how to reference this class with its proper namespace.

Copy link

ghost commented Aug 19, 2013

ah, got it -- in rails 4 cache_digests has been rolled into ActionView, so instead of CacheDigests::TemplateDigestor, it's ActionView::Digestor. you can throw this block into ApplicationController and it'll get mixed into all the etags you generate with fresh_when invocations in various controllers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment