
HTTP Caching in Ruby with Rails - craigkerstiens
https://devcenter.heroku.com/articles/http-caching-ruby-rails
======
nate
Great summary.

One problem that tripped me up with http caching in rails was invalidating
client http caches when a template changes and you're doing conditional etags
based on an object's updated at timestamp. So basically when you do
fresh_when(object), your rails app basically will only tell an http client
this thing is stale if the object's updated_at timestamp changes. It doesn't
take into account if the actually view code changes. Even worse, when your
assets get recompiled (app-123.css is now app-234.css) and the old ones don't
exist anymore, your app breaks.

I wrote about a way to fix that with a little gem I made:

[http://ninjasandrobots.com/rails-caching-a-problem-with-
etag...](http://ninjasandrobots.com/rails-caching-a-problem-with-etags-and-a-
solution)

~~~
jeremykemper
Nice fix!

Declared ETags, together with Russian Doll caching, take the next step:
automatically mixing your template and asset versions into your ETags.

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
    

This avoids the need to use global versions that blow all browser caches.
Neatly contains the scope of "freshness fallout" when you tweak a view and
deploy.

------
steveklabnik
Please note that Rails 4 will remove action and page caching, and put them in
a plugin. In addition, 'declarative etags' have been added.
[https://github.com/rails/rails/commit/ed5c938fa36995f06d4917...](https://github.com/rails/rails/commit/ed5c938fa36995f06d4917d9543ba78ed506bb8d)

Oh, and the famed 'russian doll' caching:
<https://github.com/rails/cache_digests>

------
calgaryeng
This is an old(ish) article. Any particular reason it is showing up here now ?

