From 96137e8bd0a0094d26cc0cf6f86642487a60735f Mon Sep 17 00:00:00 2001 From: Chris Eppstein Date: Mon, 27 Jun 2011 13:48:36 -0700 Subject: Add asset_url helper and refactor the asset paths so that asset hosts can be used during asset precompilation. Conflicts: actionpack/lib/action_view/asset_paths.rb actionpack/lib/sprockets/helpers/rails_helper.rb actionpack/test/template/sprockets_helper_test.rb --- actionpack/lib/action_view/asset_paths.rb | 72 ++++++++++++++++------ .../helpers/asset_tag_helpers/asset_include_tag.rb | 23 ++++--- actionpack/lib/sprockets/helpers/rails_helper.rb | 19 +++--- 3 files changed, 75 insertions(+), 39 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_view/asset_paths.rb b/actionpack/lib/action_view/asset_paths.rb index 2b1fe545a6..4974bd5426 100644 --- a/actionpack/lib/action_view/asset_paths.rb +++ b/actionpack/lib/action_view/asset_paths.rb @@ -4,7 +4,7 @@ module ActionView class AssetPaths #:nodoc: attr_reader :config, :controller - def initialize(config, controller) + def initialize(config, controller = nil) @config = config @controller = controller end @@ -19,15 +19,17 @@ module ActionView source = rewrite_extension(source, dir, ext) if ext source = rewrite_asset_path(source, dir) - - if controller && include_host - has_request = controller.respond_to?(:request) - source = rewrite_host_and_protocol(source, has_request) - end - + source = rewrite_relative_url_root(source, relative_url_root) if has_request? + source = rewrite_host_and_protocol(source) if include_host source end + # Return the filesystem path for the source + def compute_source_path(source, dir, ext) + source = rewrite_extension(source, dir, ext) if ext + File.join(config.assets_dir, dir, source) + end + def is_uri?(path) path =~ %r{^[-a-z]+://|^cid:|^//} end @@ -46,13 +48,14 @@ module ActionView relative_url_root && !source.starts_with?("#{relative_url_root}/") ? "#{relative_url_root}#{source}" : source end - def rewrite_host_and_protocol(source, has_request) - source = rewrite_relative_url_root(source, controller.config.relative_url_root) if has_request + def has_request? + controller.respond_to?(:request) + end + + def rewrite_host_and_protocol(source) host = compute_asset_host(source) - if has_request && host && !is_uri?(host) - host = "#{controller.request.protocol}#{host}" - end - "#{host}#{source}" + host = "//#{host}" if host && !is_uri?(host) + host.nil? ? source : "#{host}#{source}" end # Pick an asset host for this source. Returns +nil+ if no host is set, @@ -61,19 +64,48 @@ module ActionView # or the value returned from invoking call on an object responding to call # (proc or otherwise). def compute_asset_host(source) - if host = config.asset_host + if host = asset_host_config if host.respond_to?(:call) - case host.is_a?(Proc) ? host.arity : host.method(:call).arity - when 2 - request = controller.respond_to?(:request) && controller.request - host.call(source, request) - else - host.call(source) + args = [source] + arity = arity_of(host) + if arity > 1 && !has_request? + raise ActionController::RoutingError, "This asset host cannot be computed without a request in scope. Remove the second argument to your asset_host Proc if you do not need the request." end + args << current_request if (arity > 1 || arity < 0) && has_request? + host.call(*args) else (host =~ /%d/) ? host % (source.hash % 4) : host end end end + + def relative_url_root + if controller.respond_to?(:config) && controller.config + controller.config.relative_url_root + elsif config.respond_to?(:action_controller) && config.action_controller + config.action_controller.relative_url_root + elsif Rails.respond_to?(:application) && Rails.application.config + Rails.application.config.action_controller.relative_url_root + end + end + + def asset_host_config + if config.respond_to?(:asset_host) + config.asset_host + elsif Rails.respond_to?(:application) + Rails.application.config.action_controller.asset_host + end + end + + # Returns the current request if one exists. + def current_request + controller.request if has_request? + end + + # Returns the arity of a callable + def arity_of(callable) + callable.respond_to?(:arity) ? callable.arity : callable.method(:call).arity + end + end end diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb index e4662a2919..16d8f3f893 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb @@ -60,12 +60,16 @@ module ActionView private - def path_to_asset(source, include_host = true) - asset_paths.compute_public_path(source, asset_name.to_s.pluralize, extension, include_host) + def path_to_asset(source) + asset_paths.compute_public_path(source, asset_name.to_s.pluralize, extension) + end + + def path_to_asset_source(source) + asset_paths.compute_source_path(source, asset_name.to_s.pluralize, extension) end def compute_paths(*args) - expand_sources(*args).collect { |source| asset_paths.compute_public_path(source, asset_name.pluralize, extension, false) } + expand_sources(*args).collect { |source| path_to_asset_source(source) } end def expand_sources(sources, recursive) @@ -92,7 +96,7 @@ module ActionView def ensure_sources!(sources) sources.each do |source| - asset_file_path!(path_to_asset(source, false)) + asset_file_path!(path_to_asset_source(source)) end end @@ -123,19 +127,14 @@ module ActionView # Set mtime to the latest of the combined files to allow for # consistent ETag without a shared filesystem. - mt = asset_paths.map { |p| File.mtime(asset_file_path(p)) }.max + mt = asset_paths.map { |p| File.mtime(asset_file_path!(p)) }.max File.utime(mt, mt, joined_asset_path) end - def asset_file_path(path) - File.join(config.assets_dir, path.split('?').first) - end - - def asset_file_path!(path, error_if_file_is_uri = false) - if asset_paths.is_uri?(path) + def asset_file_path!(absolute_path, error_if_file_is_uri = false) + if asset_paths.is_uri?(absolute_path) raise(Errno::ENOENT, "Asset file #{path} is uri and cannot be merged into single file") if error_if_file_is_uri else - 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 diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 9f1f0f3b68..ef7cf9e051 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -58,23 +58,28 @@ module Sprockets end.join("\n").html_safe end + def asset_path(source, default_ext = nil, body = false) + source = source.logical_path if source.respond_to?(:logical_path) + path = asset_paths.compute_public_path(source, 'assets', default_ext) + body ? "#{path}?body=1" : path + end + private def debug_assets? params[:debug_assets] == '1' || params[:debug_assets] == 'true' end - def asset_path(source, default_ext = nil, body = false) - source = source.logical_path if source.respond_to?(:logical_path) - path = asset_paths.compute_public_path(source, Rails.application.config.assets.prefix, default_ext, true) - body ? "#{path}?body=1" : path - end - class AssetPaths < ::ActionView::AssetPaths #:nodoc: def compute_public_path(source, dir, ext=nil, include_host=true) super(source, Rails.application.config.assets.prefix, ext, include_host) end + # Return the filesystem path for the source + def compute_source_path(source, ext) + asset_for(source, ext) + end + def asset_for(source, ext) source = source.to_s return nil if is_uri?(source) @@ -104,7 +109,7 @@ module Sprockets # When included in Sprockets::Context, we need to ask the top-level config as the controller is not available def performing_caching? - @config ? @config.perform_caching : Rails.application.config.action_controller.perform_caching + @config ? @config.perform_caching : Rails.application.config.action_controller.perform_caching end end end -- cgit v1.2.3