Skip to content

Instantly share code, notes, and snippets.

@skorks
Forked from matthewtodd/asset_tag_helper.rb
Created July 8, 2011 09:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skorks/1071420 to your computer and use it in GitHub Desktop.
Save skorks/1071420 to your computer and use it in GitHub Desktop.
Rails + Sass + Asset Fingerprints + Heroku
# Ensure AssetTagHelper has been loaded before we try to monkey-patch it.
require 'action_view/helpers/asset_tag_helper'
module ActionView::Helpers::AssetTagHelper
# Insert the asset id in the filename, rather than in the query string. In
# addition to looking nicer, this also keeps any other static file handlers
# from preempting our Rack::StaticCache middleware, since these
# version-numbered files don't actually exist on disk.
def rewrite_asset_path(source)
source.insert source.rindex('.'), "-#{rails_asset_id(source)}"
end
# Exactly like the original, with calculate_asset_id extracted.
def rails_asset_id(source)
if asset_id = ENV["RAILS_ASSET_ID"]
asset_id
else
if @@cache_asset_timestamps && (asset_id = @@asset_timestamps_cache[source])
asset_id
else
asset_id = calculate_asset_id(source)
if @@cache_asset_timestamps
@@asset_timestamps_cache_guard.synchronize do
@@asset_timestamps_cache[source] = asset_id
end
end
asset_id
end
end
end
private
# Check out the sass initializer and the Rack::StaticCache setup in
# environment.rb. We're serving sass-generated stylesheets from tmp.
def calculate_asset_id(source)
case source
when %r{^/stylesheets}
digest File.join('tmp', source)
else
digest File.join('public', source)
end
end
# Prefer digest of file contents over File mtime, since File mtimes change on
# every Heroku deploy, even if the contents don't.
#
# We additionally to_i(16) the digest since Rack::StaticCache assumes version
# numbers have digits and dots only.
def digest(path)
Digest::MD5.file(path).hexdigest.to_i(16)
end
end
RAILS_GEM_VERSION = '2.3.8' unless defined? RAILS_GEM_VERSION
require File.join(File.dirname(__FILE__), 'boot')
Rails::Initializer.run do |config|
# Set far-future caching headers for static assets.
config.middleware.use 'Rack::StaticCache',
:root => 'public',
:urls => ['/images', '/javascripts']
# Serve sass-generated stylesheets on Heroku.
config.middleware.use 'Rack::StaticCache',
:root => 'tmp',
:urls => ['/stylesheets']
end
# Compile sass templates to tmp, for Heroku.
Sass::Plugin.options[:template_location] = Rails.root.join('app', 'stylesheets').to_s
Sass::Plugin.options[:css_location] = Rails.root.join('tmp', 'stylesheets').to_s
# Heroku's Rack stack includes a Heroku::StaticAssetsMiddleware that (at least
# as of 2010-06-25) blows away any Cache-Control header coming from a
# Rack::File. This would defeat the purpose of our Rack::StaticCache middleware
# setup (see config/environment.rb), so we monkey-patch it here to do nothing.
module Heroku
class StaticAssetsMiddleware
def initialize(app)
@app = app
end
def call(env)
@app.call(env)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment