Browse files

Fix javascript_include_tag when no js runtime is available

In a production environment where the assets have been precompiled, we
don't want an assets compile step to happen on the application server at
all. To ensure this, a js runtime may not be available on the app
servers. In this environment, pages using javascript_include_tag for
assets with non-standard or chained extensions were throwing 500 errors.
For instance, `javascript_include_tag('jquery.min')` would blow up.

Sprockets was attempting to build the assets being included during the
rewrite_extension step (responsible for appending a '.js' extension to
assets being included by the basename rather than a fully qualified
name). This was happening as a step to resolve #6310, which required
checking for the presence of an asset with a non-standard extension
before appending the extension.

We can check for the presence of an asset without invoking the asset
build step by using Sprockets' resolve method, which will search for the
base file without building it (and is the method that find_asset uses
internally to get the path to the asset before attempting to build it).

When rewriting the extension on an asset, these are the steps:
- If the source does not have an extension, assume that the default
  extension is desired and append it.
- If there is an extension and it doesn't match the default extension,
  check to see if a file with the precise name specified exists amongst
  the assets; if it is present, do not append the default extension.
  (This is the step that resolves #6310).

Change-Id: I74e561db064ed21c4596ba6b6b0c9b4b236f8c06
  • Loading branch information...
1 parent 966371a commit 8ce2c647d1c42c3fa738684dec2fd2923c30858d @noahsilas noahsilas committed Jun 9, 2012
@@ -155,16 +155,24 @@ def rewrite_asset_path(source, dir, options = {})
def rewrite_extension(source, dir, ext)
- source_ext = File.extname(source)
- if ext && source_ext != ".#{ext}"
- if !source_ext.empty? && (asset = asset_environment[source]) &&
- asset.pathname.to_s =~ /#{source}\Z/
- source
- else
- "#{source}.#{ext}"
- end
- else
+ source_ext = File.extname(source)[1..-1]
+ if !ext || ext == source_ext
+ return source
+ elsif source_ext.blank?
+ return "#{source}.#{ext}"
+ end
+ begin
+ pathname = asset_environment.resolve(source)
+ rescue Sprockets::FileNotFound
+ return "#{source}.#{ext}"
+ end
+ if pathname.to_s =~ /#{Regexp.escape(source)}\Z/
+ else
+ "#{source}.#{ext}"
@@ -268,6 +268,14 @@ def compute_host(source, request, options = {})
+ test "precompiled assets with an extension when no JS runtime is available" do
+ @config.assets.compile = false
+ @config.assets.digests = {'foo.min.js' => 'foo.min-f00.js'}
+ Sprockets::Index.any_instance.stubs(:build_asset).raises
+ assert_nothing_raised { javascript_include_tag('foo.min') }
+ end
test "stylesheet path through asset_path" do
assert_match %r{/assets/application-[0-9a-f]+.css}, asset_path(:application, :ext => "css")

0 comments on commit 8ce2c64

Please sign in to comment.