Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I prevent Rails 3.1 from caching static assets to Rails.cache?

I'm using CloudFlare CDN on my Rails 3.1 application. Cloudflare is a CDN that works at the DNS level. On the first hit to a static asset, CloudFlare loads it from your app then caches it in their CDN. Future requests for that asset load from the CDN instead of your app.

The problem I'm having is that if you set controller caching to true:

config.action_controller.perform_caching = true

it enables the Rack::Cache middleware. Since Rails sets a default cache control setting for static assets, those assets get written to the Rails.cache store. As a result my cache store (in my case redis) is being filled up with static assets with the url as the hash key.

Unfortunately, I can't turn off the static asset cache control headers without affecting how Cloudflare and my users' browsers cache the assets. I can't turn off controller caching or I lose page/action/fragment caching. Same result if I delete the Rack::Cache middleware.

Does anyone have any other ideas?

Update: I've opened a ticket on GitHub here.

like image 328
Jack Chu Avatar asked Aug 05 '11 21:08

Jack Chu


People also ask

What is static asset caching?

Static caching is when a browser requests a resource, the server providing the resource can tell the browser how long it should temporarily store or cache the resource. For any subsequent request for that resource, the browser uses its local copy, rather than going to the network to fetch it.

Which of the following caching techniques is are available in Rails?

This is an introduction to three types of caching techniques: page, action and fragment caching. By default Rails provides fragment caching. In order to use page and action caching you will need to add actionpack-page_caching and actionpack-action_caching to your Gemfile .

Where does Rails store cache?

Rails (as of 2.1) provides different stores for the cached data created by action and fragment caches. Page caches are always stored on disk. Rails 2.1 and above provide ActiveSupport::Cache::Store which can be used to cache strings.

What does Rails cache clear do?

cache. clear will clear your app cache. In that case rake tmp:cache:clear will just try to remove files from "#{Rails.


1 Answers

After a lot of experimentation, I've ended up doing this in my config/application.rb:

if !Rails.env.development? && !Rails.env.test?
  config.middleware.insert_before Rack::Cache, Rack::Static, urls: [config.assets.prefix], root: 'public'
end

What this does is add a Rack::Static rack middleware before requests to Rack::Cache. The Rack::Static middleware serves up urls with a matching prefix to a root directory. Here I'm giving config.assets.prefix as my url prefix which defaults to '/assets.' I'm setting the root to the 'public' directory.

Requests for this path:

/assets/jquery-e8da439bbc8fd345e34ac57c6a216318.min.js

should find it in this file:

public/assets/jquery-e8da439bbc8fd345e34ac57c6a216318.min.js

This should serve any assets directly out of the public/assets directory instead of hitting Rails::Cache at all, which will prevent it from storing the assets in the Rails cache_store. This will only work if you run the 'rake assets:precompile' in production, otherwise there will be no precompiled assets in 'public/assets'.

like image 56
Jack Chu Avatar answered Oct 05 '22 01:10

Jack Chu