3 ms·
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 condition
by nate 14y ago
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-etags-and-a-solution http://ninjasandrobots.com/rails-caching-a-problem-with-etag...
- jeremykemper 14y agoNice 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.