1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Allow customisation of asset path generation using a proc.

Set config.action_controller.asset_path_template to a proc that takes one
argument - the direct, unchanged asset path - and returns a path to that asset
using the scheme that your assets require.

This is useful if you have a setup which scales by introducing new application
servers where the mtime of the asset files may not be the same as those of the
asset files on your previous servers, but it does require your web servers to
have knowledge of the asset template paths that you rewrite to so it's not
suitable for out-of-the-box use. An example of configuring asset path
generation and rewriting these paths using Apache is included in
actionpack/lib/action_view/helpers/asset_tag_helper.rb.

Signed-off-by: wycats <wycats@gmail.com>
This commit is contained in:
Craig R Webster 2010-03-21 19:35:38 +00:00 committed by wycats
parent cf6734fdf9
commit 49bc6a249e
3 changed files with 77 additions and 2 deletions

View file

@ -108,7 +108,7 @@ module ActionView
# "http://asset%d.example.com", "https://asset1.example.com" # "http://asset%d.example.com", "https://asset1.example.com"
# ) # )
# #
# === Using asset timestamps # === Using asset path templates
# #
# By default, Rails appends asset's timestamps to all asset paths. This allows # By default, Rails appends asset's timestamps to all asset paths. This allows
# you to set a cache-expiration date for the asset far into the future, but # you to set a cache-expiration date for the asset far into the future, but
@ -133,6 +133,65 @@ module ActionView
# will request the same assets over and over again even thought they didn't # will request the same assets over and over again even thought they didn't
# change. You can use something like Live HTTP Headers for Firefox to verify # change. You can use something like Live HTTP Headers for Firefox to verify
# that the cache is indeed working. # that the cache is indeed working.
#
# This strategy works well enough for most server setups and requires the
# least configuration, but if you deploy several application servers at
# different times - say to handle a temporary spike in load - then the
# asset time stamps will be out of sync. In a setup like this you may want
# to set the way that asset paths are generated yourself.
#
# Altering the asset paths that Rails generates can be done in two ways.
# The easiest is to define the RAILS_ASSET_ID environment variable. The
# contents of this variable will always be used in preference to
# calculated timestamps. A more complex but flexible way is to set
# <tt>ActionController::Base.config.asset_path_template</tt> to a proc
# that takes the unmodified asset path and returns the path needed for
# your asset caching to work. Typically you'd do something like this in
# <tt>config/environments/production.rb</tt>:
#
# # Normally you'd calculate RELEASE_NUMBER at startup.
# RELEASE_NUMBER = 12345
# config.action_controller.asset_path_template = proc { |asset_path|
# "/release-#{RELEASE_NUMBER}#{asset_path}"
# }
#
# This example would cause the following behaviour on all servers no
# matter when they were deployed:
#
# image_tag("rails.png")
# # => <img alt="Rails" src="/release-12345/images/rails.png" />
# stylesheet_link_tag("application")
# # => <link href="/release-12345/stylesheets/application.css?1232285206" media="screen" rel="stylesheet" type="text/css" />
#
# Changing the asset_path_template does require that your web servers have
# knowledge of the asset template paths that you rewrite to so it's not
# suitable for out-of-the-box use. To use the example given above you
# could use something like this in your Apache VirtualHost configuration:
#
# <LocationMatch "^/release-\d+/(images|javascripts|stylesheets)/.*$">
# # Some browsers still send conditional-GET requests if there's a
# # Last-Modified header or an ETag header even if they haven't
# # reached the expiry date sent in the Expires header.
# Header unset Last-Modified
# Header unset ETag
# FileETag None
#
# # Assets requested using a cache-busting filename should be served
# # only once and then cached for a really long time. The HTTP/1.1
# # spec frowns on hugely-long expiration times though and suggests
# # that assets which never expire be served with an expiration date
# # 1 year from access.
# ExpiresActive On
# ExpiresDefault "access plus 1 year"
# </LocationMatch>
#
# # We use cached-busting location names with the far-future expires
# # headers to ensure that if a file does change it can force a new
# # request. The actual asset filenames are still the same though so we
# # need to rewrite the location from the cache-busting location to the
# # real asset location so that we can serve it.
# RewriteEngine On
# RewriteRule ^/release-\d+/(images|javascripts|stylesheets)/(.*)$ /$1/$2 [L]
module AssetTagHelper module AssetTagHelper
JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls', 'rails'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES) JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls', 'rails'].freeze unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES)
@ -646,7 +705,12 @@ module ActionView
source += ".#{ext}" if rewrite_extension?(source, dir, ext) source += ".#{ext}" if rewrite_extension?(source, dir, ext)
source = "/#{dir}/#{source}" unless source[0] == ?/ source = "/#{dir}/#{source}" unless source[0] == ?/
asset_path_template = config.asset_path_template
if asset_path_template && asset_path_template.respond_to?(:call)
source = asset_path_template.call(source)
else
source = rewrite_asset_path(source) source = rewrite_asset_path(source)
end
has_request = controller.respond_to?(:request) has_request = controller.respond_to?(:request)
if has_request && include_host && source !~ %r{^#{controller.config.relative_url_root}/} if has_request && include_host && source !~ %r{^#{controller.config.relative_url_root}/}

View file

@ -373,6 +373,15 @@ class AssetTagHelperTest < ActionView::TestCase
assert_equal %(<img alt="Rails" src="/images/rails.png?#{expected_time}" />), image_tag("rails.png") assert_equal %(<img alt="Rails" src="/images/rails.png?#{expected_time}" />), image_tag("rails.png")
end end
def test_proc_asset_id
@controller.config.asset_path_template = Proc.new do |asset_path|
"/assets.v12345#{asset_path}"
end
expected_path = "/assets.v12345/images/rails.png"
assert_equal %(<img alt="Rails" src="#{expected_path}" />), image_tag("rails.png")
end
def test_timebased_asset_id_with_relative_url_root def test_timebased_asset_id_with_relative_url_root
@controller.config.relative_url_root = "/collaboration/hieraki" @controller.config.relative_url_root = "/collaboration/hieraki"
expected_time = File.stat(File.expand_path(File.dirname(__FILE__) + "/../fixtures/public/images/rails.png")).mtime.to_i.to_s expected_time = File.stat(File.expand_path(File.dirname(__FILE__) + "/../fixtures/public/images/rails.png")).mtime.to_i.to_s

View file

@ -133,6 +133,8 @@ h4. Configuring Action Controller
* +config.action_controller.asset_host+ provides a string that is prepended to all of the URL-generating helpers in +AssetHelper+. This is designed to allow moving all javascript, CSS, and image files to a separate asset host. * +config.action_controller.asset_host+ provides a string that is prepended to all of the URL-generating helpers in +AssetHelper+. This is designed to allow moving all javascript, CSS, and image files to a separate asset host.
* +config.action_controller.asset_template_path+ allows you to override the default asset path generation by providing your own instructions.
* +config.action_controller.consider_all_requests_local+ is generally set to +true+ during development and +false+ during production; if it is set to +true+, then any error will cause detailed debugging information to be dumped in the HTTP response. For finer-grained control, set this to +false+ and implement +local_request?+ to specify which requests should provide debugging information on errors. * +config.action_controller.consider_all_requests_local+ is generally set to +true+ during development and +false+ during production; if it is set to +true+, then any error will cause detailed debugging information to be dumped in the HTTP response. For finer-grained control, set this to +false+ and implement +local_request?+ to specify which requests should provide debugging information on errors.
* +config.action_controller.allow_concurrency+ should be set to +true+ to allow concurrent (threadsafe) action processing. Set to +false+ by default. You probably don't want to call this one directly, though, because a series of other adjustments need to be made for threadsafe mode to work properly. Instead, you should simply call +config.threadsafe!+ inside your +production.rb+ file, which makes all the necessary adjustments. * +config.action_controller.allow_concurrency+ should be set to +true+ to allow concurrent (threadsafe) action processing. Set to +false+ by default. You probably don't want to call this one directly, though, because a series of other adjustments need to be made for threadsafe mode to work properly. Instead, you should simply call +config.threadsafe!+ inside your +production.rb+ file, which makes all the necessary adjustments.