Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Simple asset caching, without time-based expiry. Adds support for `turbo-sprockets-rails3` #43

wants to merge 1 commit into from

5 participants


This is an alternative to #42, which simply removes any assets that aren't referenced by manifest.yml.

It provides a strong guarantee that the public/assets cache won't grow out of control, by clearing the cache if any exceptions are raised during the cleanup. I know it's usually not a good idea to rescue Exception, but you never know what might happen when you're dealing with 2.2 million apps. Anything could be monkey-patched by a rogue gem, and anything could break :)

Since most Rails 3 apps won't benefit from this caching unless they are using my turbo-sprockets-rails3 gem, I think it would be appropriate to add the following conditional:

  # assets caching code ...

Let me know what you think about that.

Note that cache_load "public/assets" at the beginning doesn't need to be conditional, since it just won't do anything if public/assets isn't cached.


Have opened a pull request with the turbo-sprockets-rails3 conditional at #44

@jjb jjb referenced this pull request in ndbroadbent/turbo-sprockets-rails3

issue with 3.2.9 and heroku #33

@schneems schneems closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 30 additions and 0 deletions.
  1. +30 −0 lib/language_pack/rails3.rb
30 lib/language_pack/rails3.rb
@@ -43,6 +43,9 @@ def run_assets_precompile_rake_task
if File.exists?("public/assets/manifest.yml")
puts "Detected manifest.yml, assuming assets were compiled locally"
+ FileUtils.mkdir_p('public')
+ cache_load "public/assets"
ENV["RAILS_GROUPS"] ||= "assets"
ENV["RAILS_ENV"] ||= "production"
@@ -53,6 +56,13 @@ def run_assets_precompile_rake_task
if $?.success?
log "assets_precompile", :status => "success"
puts "Asset precompilation completed (#{"%.2f" % time}s)"
+ if clean_unreferenced_assets
+ cache_store "public/assets"
+ else
+ # If something goes wrong, clear the assets cache before the next run.
+ cache_clear "public/assets"
+ end
log "assets_precompile", :status => "failure"
puts "Precompiling assets failed, enabling runtime asset compilation"
@@ -65,6 +75,26 @@ def run_assets_precompile_rake_task
+ # Removes assets that aren't referenced by manifest.yml
+ def clean_unreferenced_assets
+ return false unless File.exists?("public/assets/manifest.yml")
+ digests = YAML.load_file("public/assets/manifest.yml")
+ known_assets = digests.flatten.flat_map {|a| [a, "#{a}.gz"] }.map {|a| File.join('public/assets', a) }
+ puts "Cleaning up the assets cache."
+ Dir.glob('public/assets/**/*').each do |asset|
+ next if || asset.include?('manifest.yml')
+ # Remove asset if not referenced by manifest.yml
+ unless known_assets.include?(asset)
+ puts "Removing unreferenced asset: #{asset.sub(%r{.*/public/assets/}, '')}"
+ FileUtils.rm_f asset
+ end
+ end
+ rescue Exception => ex
+ puts "Something failed while cleaning up old assets! => #{ex.message.inspect}"
+ false
+ end
# setup the database url as an environment variable
def setup_database_url_env
ENV["DATABASE_URL"] ||= begin
Something went wrong with that request. Please try again.