diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index babb9db38a..14cdc7a025 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -1,6 +1,7 @@
require 'cgi'
require 'action_view/helpers/url_helper'
require 'action_view/helpers/tag_helper'
+require 'active_support/core_ext/file'
module ActionView
module Helpers #:nodoc:
@@ -285,7 +286,7 @@ module ActionView
end
javascript_src_tag(joined_javascript_name, options)
else
- expand_javascript_sources(sources, recursive).collect { |source| javascript_src_tag(source, options) }.join("\n")
+ ensure_javascript_sources!(expand_javascript_sources(sources, recursive)).collect { |source| javascript_src_tag(source, options) }.join("\n")
end
end
@@ -434,7 +435,7 @@ module ActionView
end
stylesheet_tag(joined_stylesheet_name, options)
else
- expand_stylesheet_sources(sources, recursive).collect { |source| stylesheet_tag(source, options) }.join("\n")
+ ensure_stylesheet_sources!(expand_stylesheet_sources(sources, recursive)).collect { |source| stylesheet_tag(source, options) }.join("\n")
end
end
@@ -664,13 +665,28 @@ module ActionView
end
end
+ def ensure_stylesheet_sources!(sources)
+ sources.each do |source|
+ asset_file_path!(path_to_stylesheet(source))
+ end
+ return sources
+ end
+
+ def ensure_javascript_sources!(sources)
+ sources.each do |source|
+ asset_file_path!(path_to_javascript(source))
+ end
+ return sources
+ end
+
def join_asset_file_contents(paths)
- paths.collect { |path| File.read(asset_file_path(path)) }.join("\n\n")
+ paths.collect { |path| File.read(asset_file_path!(path)) }.join("\n\n")
end
def write_asset_file_contents(joined_asset_path, asset_paths)
+
FileUtils.mkdir_p(File.dirname(joined_asset_path))
- File.open(joined_asset_path, "w+") { |cache| cache.write(join_asset_file_contents(asset_paths)) }
+ File.atomic_write(joined_asset_path) { |cache| cache.write(join_asset_file_contents(asset_paths)) }
# Set mtime to the latest of the combined files to allow for
# consistent ETag without a shared filesystem.
@@ -682,6 +698,14 @@ module ActionView
File.join(ASSETS_DIR, path.split('?').first)
end
+ def asset_file_path!(path)
+ unless path =~ %r{^[-a-z]+://}
+ absolute_path = asset_file_path(path)
+ raise(Errno::ENOENT, "Asset file not found at '#{absolute_path}'" ) unless File.exist?(absolute_path)
+ return absolute_path
+ end
+ end
+
def collect_asset_files(*path)
dir = path.first
diff --git a/actionpack/test/fixtures/public/elsewhere/cools.js b/actionpack/test/fixtures/public/elsewhere/cools.js
new file mode 100644
index 0000000000..6e12fe29c4
--- /dev/null
+++ b/actionpack/test/fixtures/public/elsewhere/cools.js
@@ -0,0 +1 @@
+// cools.js
\ No newline at end of file
diff --git a/actionpack/test/fixtures/public/elsewhere/file.css b/actionpack/test/fixtures/public/elsewhere/file.css
new file mode 100644
index 0000000000..6aea0733b1
--- /dev/null
+++ b/actionpack/test/fixtures/public/elsewhere/file.css
@@ -0,0 +1 @@
+/*file.css*/
\ No newline at end of file
diff --git a/actionpack/test/fixtures/public/javascripts/common.javascript b/actionpack/test/fixtures/public/javascripts/common.javascript
new file mode 100644
index 0000000000..2ae1929056
--- /dev/null
+++ b/actionpack/test/fixtures/public/javascripts/common.javascript
@@ -0,0 +1 @@
+// common.javascript
\ No newline at end of file
diff --git a/actionpack/test/fixtures/public/stylesheets/random.styles b/actionpack/test/fixtures/public/stylesheets/random.styles
new file mode 100644
index 0000000000..d4eeead95c
--- /dev/null
+++ b/actionpack/test/fixtures/public/stylesheets/random.styles
@@ -0,0 +1 @@
+/* random.styles */
\ No newline at end of file
diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb
index f1dad9f50e..65289a59bc 100644
--- a/actionpack/test/template/asset_tag_helper_test.rb
+++ b/actionpack/test/template/asset_tag_helper_test.rb
@@ -75,22 +75,22 @@ class AssetTagHelperTest < ActionView::TestCase
}
JavascriptIncludeToTag = {
- %(javascript_include_tag("xmlhr")) => %(),
- %(javascript_include_tag("xmlhr.js")) => %(),
- %(javascript_include_tag("xmlhr", :lang => "vbscript")) => %(),
+ %(javascript_include_tag("bank")) => %(),
+ %(javascript_include_tag("bank.js")) => %(),
+ %(javascript_include_tag("bank", :lang => "vbscript")) => %(),
%(javascript_include_tag("common.javascript", "/elsewhere/cools")) => %(\n),
%(javascript_include_tag(:defaults)) => %(\n\n\n\n),
%(javascript_include_tag(:all)) => %(\n\n\n\n\n\n\n),
%(javascript_include_tag(:all, :recursive => true)) => %(\n\n\n\n\n\n\n\n),
- %(javascript_include_tag(:defaults, "test")) => %(\n\n\n\n\n),
- %(javascript_include_tag("test", :defaults)) => %(\n\n\n\n\n)
+ %(javascript_include_tag(:defaults, "bank")) => %(\n\n\n\n\n),
+ %(javascript_include_tag("bank", :defaults)) => %(\n\n\n\n\n)
}
StylePathToTag = {
- %(stylesheet_path("style")) => %(/stylesheets/style.css),
- %(stylesheet_path("style.css")) => %(/stylesheets/style.css),
- %(stylesheet_path('dir/file')) => %(/stylesheets/dir/file.css),
- %(stylesheet_path('/dir/file.rcss')) => %(/dir/file.rcss)
+ %(stylesheet_path("bank")) => %(/stylesheets/bank.css),
+ %(stylesheet_path("bank.css")) => %(/stylesheets/bank.css),
+ %(stylesheet_path('subdir/subdir')) => %(/stylesheets/subdir/subdir.css),
+ %(stylesheet_path('/subdir/subdir.css')) => %(/subdir/subdir.css)
}
PathToStyleToTag = {
@@ -101,15 +101,16 @@ class AssetTagHelperTest < ActionView::TestCase
}
StyleLinkToTag = {
- %(stylesheet_link_tag("style")) => %(),
- %(stylesheet_link_tag("style.css")) => %(),
- %(stylesheet_link_tag("/dir/file")) => %(),
- %(stylesheet_link_tag("dir/file")) => %(),
- %(stylesheet_link_tag("style", :media => "all")) => %(),
+ %(stylesheet_link_tag("bank")) => %(),
+ %(stylesheet_link_tag("bank.css")) => %(),
+ %(stylesheet_link_tag("/elsewhere/file")) => %(),
+ %(stylesheet_link_tag("subdir/subdir")) => %(),
+ %(stylesheet_link_tag("bank", :media => "all")) => %(),
%(stylesheet_link_tag(:all)) => %(\n\n),
%(stylesheet_link_tag(:all, :recursive => true)) => %(\n\n\n),
%(stylesheet_link_tag(:all, :media => "all")) => %(\n\n),
- %(stylesheet_link_tag("random.styles", "/css/stylish")) => %(\n),
+ %(stylesheet_link_tag("random.styles", "/elsewhere/file")) => %(\n),
+
%(stylesheet_link_tag("http://www.example.com/styles/style")) => %()
}
@@ -160,6 +161,20 @@ class AssetTagHelperTest < ActionView::TestCase
JavascriptIncludeToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
+ def test_javascript_include_tag_with_missing_source
+ assert_raise(Errno::ENOENT) {
+ javascript_include_tag('missing_security_guard')
+ }
+
+ assert_raise(Errno::ENOENT) {
+ javascript_include_tag(:defaults, 'missing_security_guard')
+ }
+
+ assert_nothing_raised {
+ javascript_include_tag('http://example.com/css/missing_security_guard')
+ }
+ end
+
def test_javascript_include_tag_with_given_asset_id
ENV["RAILS_ASSET_ID"] = "1"
assert_dom_equal(%(\n\n\n\n), javascript_include_tag(:defaults))
@@ -167,26 +182,27 @@ class AssetTagHelperTest < ActionView::TestCase
def test_register_javascript_include_default
ENV["RAILS_ASSET_ID"] = ""
- ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'slider'
- assert_dom_equal %(\n\n\n\n\n), javascript_include_tag(:defaults)
+ ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'bank'
+ assert_dom_equal %(\n\n\n\n\n), javascript_include_tag(:defaults)
end
def test_register_javascript_include_default_mixed_defaults
ENV["RAILS_ASSET_ID"] = ""
- ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'slider'
- ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'lib1', '/elsewhere/blub/lib2'
- assert_dom_equal %(\n\n\n\n\n\n\n), javascript_include_tag(:defaults)
+ ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'bank'
+ ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'robber', '/elsewhere/cools.js'
+ assert_dom_equal %(\n\n\n\n\n\n\n), javascript_include_tag(:defaults)
end
def test_custom_javascript_expansions
- ActionView::Helpers::AssetTagHelper::register_javascript_expansion :monkey => ["head", "body", "tail"]
- assert_dom_equal %(\n\n\n\n), javascript_include_tag('first', :monkey, 'last')
+ ENV["RAILS_ASSET_ID"] = ""
+ ActionView::Helpers::AssetTagHelper::register_javascript_expansion :robbery => ["bank", "robber"]
+ assert_dom_equal %(\n\n\n), javascript_include_tag('controls', :robbery, 'effects')
end
def test_custom_javascript_expansions_and_defaults_puts_application_js_at_the_end
ENV["RAILS_ASSET_ID"] = ""
- ActionView::Helpers::AssetTagHelper::register_javascript_expansion :monkey => ["head", "body", "tail"]
- assert_dom_equal %(\n\n\n\n\n\n\n\n\n), javascript_include_tag('first', :defaults, :monkey, 'last')
+ ActionView::Helpers::AssetTagHelper::register_javascript_expansion :robbery => ["bank", "robber"]
+ assert_dom_equal %(\n\n\n\n\n\n\n\n), javascript_include_tag('controls',:defaults, :robbery, 'effects')
end
def test_custom_javascript_expansions_with_undefined_symbol
@@ -195,6 +211,7 @@ class AssetTagHelperTest < ActionView::TestCase
end
def test_stylesheet_path
+ ENV["RAILS_ASSET_ID"] = ""
StylePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
@@ -207,9 +224,20 @@ class AssetTagHelperTest < ActionView::TestCase
StyleLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
+ def test_stylesheet_link_tag_with_missing_source
+ assert_raise(Errno::ENOENT) {
+ stylesheet_link_tag('missing_security_guard')
+ }
+
+ assert_nothing_raised {
+ stylesheet_link_tag('http://example.com/css/missing_security_guard')
+ }
+ end
+
def test_custom_stylesheet_expansions
- ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :monkey => ["head", "body", "tail"]
- assert_dom_equal %(\n\n\n\n), stylesheet_link_tag('first', :monkey, 'last')
+ ENV["RAILS_ASSET_ID"] = ''
+ ActionView::Helpers::AssetTagHelper::register_stylesheet_expansion :robbery => ["bank", "robber"]
+ assert_dom_equal %(\n\n\n), stylesheet_link_tag('version.1.0', :robbery, 'subdir/subdir')
end
def test_custom_stylesheet_expansions_with_undefined_symbol
@@ -546,8 +574,14 @@ class AssetTagHelperTest < ActionView::TestCase
stylesheet_link_tag(:all, :cache => true)
)
- expected = Dir["#{ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR}/*.css"].map { |p| File.mtime(p) }.max
- assert_equal expected, File.mtime(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
+ files_to_be_joined = Dir["#{ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR}/[^all]*.css"]
+
+ expected_mtime = files_to_be_joined.map { |p| File.mtime(p) }.max
+ assert_equal expected_mtime, File.mtime(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
+
+ bytes_added_by_join = "\n\n".size * files_to_be_joined.size - "\n\n".size
+ expected_size = files_to_be_joined.sum { |p| File.size(p) } + bytes_added_by_join
+ assert_equal expected_size, File.size(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
assert_dom_equal(
%(),
@@ -598,6 +632,28 @@ class AssetTagHelperTest < ActionView::TestCase
FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::ASSETS_DIR, 'absolute'))
end
+ def test_caching_stylesheet_link_tag_when_caching_on_and_missing_css_file
+ ENV["RAILS_ASSET_ID"] = ""
+ ActionController::Base.asset_host = 'http://a0.example.com'
+ ActionController::Base.perform_caching = true
+
+ assert_raise(Errno::ENOENT) {
+ stylesheet_link_tag('bank', 'robber', 'missing_security_guard', :cache => true)
+ }
+
+ assert ! File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
+
+ assert_raise(Errno::ENOENT) {
+ stylesheet_link_tag('bank', 'robber', 'missing_security_guard', :cache => "money")
+ }
+
+ assert ! File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css'))
+
+ ensure
+ FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
+ FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css'))
+ end
+
def test_caching_stylesheet_link_tag_when_caching_on_with_proc_asset_host
ENV["RAILS_ASSET_ID"] = ""
ActionController::Base.asset_host = Proc.new { |source| "http://a#{source.length}.example.com" }
@@ -625,8 +681,10 @@ class AssetTagHelperTest < ActionView::TestCase
stylesheet_link_tag(:all, :cache => true)
)
- expected = Dir["#{ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR}/*.css"].map { |p| File.mtime(p) }.max
- assert_equal expected, File.mtime(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
+ files_to_be_joined = Dir["#{ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR}/[^all]*.css"]
+
+ expected_mtime = files_to_be_joined.map { |p| File.mtime(p) }.max
+ assert_equal expected_mtime, File.mtime(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
assert_dom_equal(
%(),