diff options
Diffstat (limited to 'actionpack/lib')
19 files changed, 236 insertions, 94 deletions
diff --git a/actionpack/lib/action_controller/log_subscriber.rb b/actionpack/lib/action_controller/log_subscriber.rb index 8d813a8e38..35e29398e6 100644 --- a/actionpack/lib/action_controller/log_subscriber.rb +++ b/actionpack/lib/action_controller/log_subscriber.rb @@ -10,7 +10,7 @@ module ActionController format = payload[:format] format = format.to_s.upcase if format.is_a?(Symbol) - info " Processing by #{payload[:controller]}##{payload[:action]} as #{format}" + info "Processing by #{payload[:controller]}##{payload[:action]} as #{format}" info " Parameters: #{params.inspect}" unless params.empty? end @@ -20,10 +20,11 @@ module ActionController status = payload[:status] if status.nil? && payload[:exception].present? - status = Rack::Utils.status_code(ActionDispatch::ShowExceptions.rescue_responses[payload[:exception].first]) rescue nil - end + status = Rack::Utils.status_code(ActionDispatch::ShowExceptions.rescue_responses[payload[:exception].first]) rescue nil + end message = "Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in %.0fms" % event.duration message << " (#{additions.join(" | ")})" unless additions.blank? + message << "\n" info(message) end @@ -59,4 +60,4 @@ module ActionController end end -ActionController::LogSubscriber.attach_to :action_controller
\ No newline at end of file +ActionController::LogSubscriber.attach_to :action_controller diff --git a/actionpack/lib/action_controller/metal/data_streaming.rb b/actionpack/lib/action_controller/metal/data_streaming.rb index 623a9873fc..50827d8107 100644 --- a/actionpack/lib/action_controller/metal/data_streaming.rb +++ b/actionpack/lib/action_controller/metal/data_streaming.rb @@ -26,8 +26,11 @@ module ActionController #:nodoc: # Options: # * <tt>:filename</tt> - suggests a filename for the browser to use. # Defaults to <tt>File.basename(path)</tt>. - # * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'. You can specify - # either a string or a symbol for a registered type register with <tt>Mime::Type.register</tt>, for example :json + # * <tt>:type</tt> - specifies an HTTP content type. + # You can specify either a string or a symbol for a registered type register with + # <tt>Mime::Type.register</tt>, for example :json + # If omitted, type will be guessed from the file extension specified in <tt>:filename</tt>. + # If no content type is registered for the extension, default type 'application/octet-stream' will be used. # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded. # Valid values are 'inline' and 'attachment' (default). # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'. @@ -84,6 +87,8 @@ module ActionController #:nodoc: # * <tt>:filename</tt> - suggests a filename for the browser to use. # * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'. You can specify # either a string or a symbol for a registered type register with <tt>Mime::Type.register</tt>, for example :json + # If omitted, type will be guessed from the file extension specified in <tt>:filename</tt>. + # If no content type is registered for the extension, default type 'application/octet-stream' will be used. # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded. # Valid values are 'inline' and 'attachment' (default). # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'. @@ -108,6 +113,8 @@ module ActionController #:nodoc: private def send_file_headers!(options) + type_provided = options.has_key?(:type) + options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options)) [:type, :disposition].each do |arg| raise ArgumentError, ":#{arg} option required" if options[arg].nil? @@ -123,6 +130,10 @@ module ActionController #:nodoc: raise ArgumentError, "Unknown MIME type #{options[:type]}" unless extension self.content_type = extension else + if !type_provided && options[:filename] + # If type wasn't provided, try guessing from file extension. + content_type = Mime::Type.lookup_by_extension(File.extname(options[:filename]).downcase.tr('.','')) || content_type + end self.content_type = content_type end diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb index ebadb29ea7..f3b7357e64 100644 --- a/actionpack/lib/action_controller/metal/responder.rb +++ b/actionpack/lib/action_controller/metal/responder.rb @@ -162,6 +162,11 @@ module ActionController #:nodoc: navigation_behavior(e) end + # to_js simply tries to render a template. If no template is found, raises the error. + def to_js + default_render + end + # All other formats follow the procedure below. First we try to render a # template, if the template is not available, we verify if the resource # responds to :to_format and display it. diff --git a/actionpack/lib/action_controller/railtie.rb b/actionpack/lib/action_controller/railtie.rb index d2ba052c8d..f0c29825ba 100644 --- a/actionpack/lib/action_controller/railtie.rb +++ b/actionpack/lib/action_controller/railtie.rb @@ -4,7 +4,6 @@ require "action_dispatch/railtie" require "action_view/railtie" require "abstract_controller/railties/routes_helpers" require "action_controller/railties/paths" -require "sprockets/railtie" module ActionController class Railtie < Rails::Railtie diff --git a/actionpack/lib/action_dispatch/http/mime_types.rb b/actionpack/lib/action_dispatch/http/mime_types.rb index 68f37d2f65..3da4f91051 100644 --- a/actionpack/lib/action_dispatch/http/mime_types.rb +++ b/actionpack/lib/action_dispatch/http/mime_types.rb @@ -7,6 +7,15 @@ Mime::Type.register "text/javascript", :js, %w( application/javascript applicati Mime::Type.register "text/css", :css Mime::Type.register "text/calendar", :ics Mime::Type.register "text/csv", :csv + +Mime::Type.register "image/png", :png, [], %w(png) +Mime::Type.register "image/jpeg", :jpeg, [], %w(jpg jpeg jpe) +Mime::Type.register "image/gif", :gif, [], %w(gif) +Mime::Type.register "image/bmp", :bmp, [], %w(bmp) +Mime::Type.register "image/tiff", :tiff, [], %w(tif tiff) + +Mime::Type.register "video/mpeg", :mpeg, [], %w(mpg mpeg mpe) + Mime::Type.register "application/xml", :xml, %w( text/xml application/x-xml ) Mime::Type.register "application/rss+xml", :rss Mime::Type.register "application/atom+xml", :atom @@ -19,5 +28,8 @@ Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form # http://www.json.org/JSONRequest.html Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest ) +Mime::Type.register "application/pdf", :pdf, [], %w(pdf) +Mime::Type.register "application/zip", :zip, [], %w(zip) + # Create Mime::ALL but do not add it to the SET. Mime::ALL = Mime::Type.new("*/*", :all, []) diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index 8cee9ecdc4..1c312f2587 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -129,6 +129,11 @@ module ActionDispatch @cookies[name.to_s] end + def key?(name) + @cookies.key?(name.to_s) + end + alias :has_key? :key? + def update(other_hash) @cookies.update other_hash.stringify_keys self diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb index 82c4fadb50..49aef0bf72 100644 --- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb +++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb @@ -182,10 +182,12 @@ module ActionDispatch if record.is_a?(Symbol) || record.is_a?(String) route << record - else + elsif record route << ActiveModel::Naming.route_key(record) route = [route.join("_").singularize] if inflection == :singular route << "index" if ActiveModel::Naming.uncountable?(record) && inflection == :plural + else + raise ArgumentError, "Nil location provided. Can't build URI." end route << routing_type(options) diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb index 367c295cf5..f668b81b45 100644 --- a/actionpack/lib/action_dispatch/testing/test_process.rb +++ b/actionpack/lib/action_dispatch/testing/test_process.rb @@ -39,7 +39,7 @@ module ActionDispatch # # post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png', :binary) def fixture_file_upload(path, mime_type = nil, binary = false) - fixture_path = ActionController::TestCase.send(:fixture_path) if ActionController::TestCase.respond_to?(:fixture_path) + fixture_path = self.class.fixture_path if self.class.respond_to?(:fixture_path) Rack::Test::UploadedFile.new("#{fixture_path}#{path}", mime_type, binary) end end diff --git a/actionpack/lib/action_pack/version.rb b/actionpack/lib/action_pack/version.rb index fcf0eb9565..add6b56425 100644 --- a/actionpack/lib/action_pack/version.rb +++ b/actionpack/lib/action_pack/version.rb @@ -1,9 +1,9 @@ module ActionPack module VERSION #:nodoc: MAJOR = 3 - MINOR = 1 + MINOR = 2 TINY = 0 - PRE = "rc1" + PRE = "beta" STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.') end diff --git a/actionpack/lib/action_view/asset_paths.rb b/actionpack/lib/action_view/asset_paths.rb index 2b1fe545a6..4dd02755d3 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 @@ -13,21 +13,29 @@ module ActionView # Prefix with <tt>/dir/</tt> if lacking a leading +/+. Account for relative URL # roots. Rewrite the asset path for cache-busting asset ids. Include # asset host, if configured, with the correct request protocol. - def compute_public_path(source, dir, ext = nil, include_host = true) + # + # When include_host is true and the asset host does not specify the protocol + # the protocol parameter specifies how the protocol will be added. + # When :relative (default), the protocol will be determined by the client using current protocol + # When :request, the protocol will be the request protocol + # Otherwise, the protocol is used (E.g. :http, :https, etc) + def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil) source = source.to_s return source if is_uri?(source) 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, protocol) 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 +54,45 @@ 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, protocol = nil) host = compute_asset_host(source) - if has_request && host && !is_uri?(host) - host = "#{controller.request.protocol}#{host}" + if host && !is_uri?(host) + if (protocol || default_protocol) == :request && !has_request? + host = nil + else + host = "#{compute_protocol(protocol)}#{host}" + end + end + host.nil? ? source : "#{host}#{source}" + end + + def compute_protocol(protocol) + protocol ||= default_protocol + case protocol + when :relative + "//" + when :request + unless @controller + invalid_asset_host!("The protocol requested was :request. Consider using :relative instead.") + end + @controller.request.protocol + else + "#{protocol}://" end - "#{host}#{source}" + end + + def default_protocol + protocol = @config.action_controller.default_asset_host_protocol if @config.action_controller.present? + protocol ||= @config.default_asset_host_protocol + protocol || (has_request? ? :request : :relative) + end + + def invalid_asset_host!(help_message) + raise ActionController::RoutingError, "This asset host cannot be computed without a request in scope. #{help_message}" end # Pick an asset host for this source. Returns +nil+ if no host is set, @@ -61,19 +101,45 @@ 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? + invalid_asset_host!("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 + config = controller.config if controller.respond_to?(:config) + config ||= config.action_controller if config.action_controller.present? + config ||= config + config.relative_url_root + end + + def asset_host_config + if config.action_controller.present? + config.action_controller.asset_host + else + config.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_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 7970176d37..0c3f011c92 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -347,7 +347,7 @@ module ActionView src = options[:src] = path_to_image(source) unless src =~ /^cid:/ - options[:alt] = options.fetch(:alt){ File.basename(src, '.*').capitalize } + options[:alt] = options.fetch(:alt){ image_alt(src) } end if size = options.delete(:size) @@ -362,6 +362,10 @@ module ActionView tag("img", options) end + def image_alt(src) + File.basename(src, '.*').sub(/-[[:xdigit:]]{32}\z/, '').capitalize + end + # Returns an html video tag for the +sources+. If +sources+ is a string, # a single video tag will be returned. If +sources+ is an array, a video # tag with nested source tags for each source will be returned. The 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..3c05173a1b 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, include_host = true, protocol = nil) + asset_paths.compute_public_path(source, asset_name.to_s.pluralize, extension, include_host, protocol) + 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/action_view/helpers/asset_tag_helpers/asset_paths.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb index 12a304b395..8b35aa8896 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb @@ -1,3 +1,4 @@ +require 'thread' require 'active_support/core_ext/file' module ActionView diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb index e4f11c9bc7..8c25d38bbd 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb @@ -16,7 +16,8 @@ module ActionView end def asset_tag(source, options) - tag("link", { "rel" => "stylesheet", "type" => Mime::CSS, "media" => "screen", "href" => ERB::Util.html_escape(path_to_asset(source)) }.merge(options), false, false) + # We force the :request protocol here to avoid a double-download bug in IE7 and IE8 + tag("link", { "rel" => "stylesheet", "type" => Mime::CSS, "media" => "screen", "href" => ERB::Util.html_escape(path_to_asset(source, true, :request)) }.merge(options), false, false) end def custom_dir @@ -52,7 +53,7 @@ module ActionView # If the +source+ filename has no extension, <tt>.css</tt> will be appended (except for explicit URIs). # Full paths from the document root will be passed through. # Used internally by +stylesheet_link_tag+ to build the stylesheet path. - # + # # ==== Examples # stylesheet_path "style" # => /stylesheets/style.css # stylesheet_path "dir/style.css" # => /stylesheets/dir/style.css @@ -60,11 +61,7 @@ module ActionView # stylesheet_path "http://www.example.com/css/style" # => http://www.example.com/css/style # stylesheet_path "http://www.example.com/css/style.css" # => http://www.example.com/css/style.css def stylesheet_path(source) - if config.use_sprockets - asset_path(source, 'css') - else - asset_paths.compute_public_path(source, 'stylesheets', 'css') - end + asset_paths.compute_public_path(source, 'stylesheets', 'css', true, :request) end alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with a stylesheet_path named route diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 0ef2357368..3a30263b49 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -4,6 +4,7 @@ require 'action_view/helpers/tag_helper' require 'action_view/helpers/form_tag_helper' require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/hash/slice' +require 'active_support/core_ext/module/method_names' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/output_safety' require 'active_support/core_ext/array/extract_options' @@ -567,18 +568,13 @@ module ActionView # ... # <% end %> # - # In addition, you may want to have access to the current iteration index. - # In that case, you can use a similar method called fields_for_with_index - # which receives a block with an extra parameter: + # When projects is already an association on Person you can use + # +accepts_nested_attributes_for+ to define the writer method for you: # - # <%= form_for @person do |person_form| %> - # ... - # <%= person_form.fields_for_with_index :projects do |project_fields, index| %> - # Position: <%= index %> - # Name: <%= project_fields.text_field :name %> - # <% end %> - # ... - # <% end %> + # class Person < ActiveRecord::Base + # has_many :projects + # accepts_nested_attributes_for :projects + # end # # If you want to destroy any of the associated models through the # form, you have to enable it first using the <tt>:allow_destroy</tt> @@ -1153,7 +1149,7 @@ module ActionView options["name"] ||= tag_name_with_index(@auto_index) options["id"] = options.fetch("id"){ tag_id_with_index(@auto_index) } else - options["name"] ||= tag_name + (options.has_key?('multiple') ? '[]' : '') + options["name"] ||= tag_name + (options['multiple'] ? '[]' : '') options["id"] = options.fetch("id"){ tag_id } end end @@ -1233,13 +1229,6 @@ module ActionView RUBY_EVAL end - # Check +fields_for+ for docs and examples. - def fields_for_with_index(record_name, record_object = nil, fields_options = {}, &block) - index = fields_options[:index] || options[:child_index] || nested_child_index(@object_name) - block_with_index = Proc.new{ |obj| block.call(obj, index) } - fields_for(record_name, record_object, fields_options, &block_with_index) - end - def fields_for(record_name, record_object = nil, fields_options = {}, &block) fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options? fields_options[:builder] ||= options[:builder] diff --git a/actionpack/lib/action_view/log_subscriber.rb b/actionpack/lib/action_view/log_subscriber.rb index 29ffbd6fdd..bf90d012bf 100644 --- a/actionpack/lib/action_view/log_subscriber.rb +++ b/actionpack/lib/action_view/log_subscriber.rb @@ -4,7 +4,7 @@ module ActionView # Provides functionality so that Rails can output logs from Action View. class LogSubscriber < ActiveSupport::LogSubscriber def render_template(event) - message = "Rendered #{from_rails_root(event.payload[:identifier])}" + message = " Rendered #{from_rails_root(event.payload[:identifier])}" message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout] message << (" (%.1fms)" % event.duration) info(message) diff --git a/actionpack/lib/sprockets/assets.rake b/actionpack/lib/sprockets/assets.rake new file mode 100644 index 0000000000..0236350576 --- /dev/null +++ b/actionpack/lib/sprockets/assets.rake @@ -0,0 +1,26 @@ +namespace :assets do + desc "Compile all the assets named in config.assets.precompile" + task :precompile do + if ENV["RAILS_GROUPS"].to_s.empty? + ENV["RAILS_GROUPS"] = "assets" + Kernel.exec $0, *ARGV + else + Rake::Task["environment"].invoke + Sprockets::Helpers::RailsHelper + + assets = Rails.application.config.assets.precompile + Rails.application.assets.precompile(*assets) + end + end + + desc "Remove compiled assets" + task :clean => :environment do + assets = Rails.application.config.assets + public_asset_path = Rails.public_path + assets.prefix + file_list = FileList.new("#{public_asset_path}/**/*") + file_list.each do |file| + rm_rf file + rm_rf "#{file}.gz" + end + end +end diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb index 9f1f0f3b68..7d709de9e2 100644 --- a/actionpack/lib/sprockets/helpers/rails_helper.rb +++ b/actionpack/lib/sprockets/helpers/rails_helper.rb @@ -1,4 +1,4 @@ -require "action_view/helpers" +require "action_view" module Sprockets module Helpers @@ -10,7 +10,16 @@ module Sprockets @asset_paths ||= begin config = self.config if respond_to?(:config) controller = self.controller if respond_to?(:controller) - RailsHelper::AssetPaths.new(config, controller) + config ||= Rails.application.config + if config.action_controller.present? + config.action_controller.default_asset_host_protocol ||= :relative + else + config.default_asset_host_protocol ||= :relative + end + paths = RailsHelper::AssetPaths.new(config, controller) + paths.asset_environment = asset_environment + paths.asset_prefix = asset_prefix + paths end end @@ -50,7 +59,7 @@ module Sprockets 'rel' => "stylesheet", 'type' => "text/css", 'media' => "screen", - 'href' => asset_path(source, 'css', body) + 'href' => asset_path(source, 'css', body, :request) }.merge(options.stringify_keys) tag 'link', tag_options @@ -58,35 +67,59 @@ module Sprockets end.join("\n").html_safe end + def asset_path(source, default_ext = nil, body = false, protocol = nil) + source = source.logical_path if source.respond_to?(:logical_path) + path = asset_paths.compute_public_path(source, 'assets', default_ext, true, protocol) + 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 + # Override to specify an alternative prefix for asset path generation. + # When combined with a custom +asset_environment+, this can be used to + # implement themes that can take advantage of the asset pipeline. + # + # If you only want to change where the assets are mounted, refer to + # +config.assets.prefix+ instead. + def asset_prefix + Rails.application.config.assets.prefix + end + + # Override to specify an alternative asset environment for asset + # path generation. The environment should already have been mounted + # at the prefix returned by +asset_prefix+. + def asset_environment + Rails.application.assets 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) + attr_accessor :asset_environment, :asset_prefix + + def compute_public_path(source, dir, ext=nil, include_host=true, protocol=nil) + super(source, asset_prefix, ext, include_host, protocol) + 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) source = rewrite_extension(source, nil, ext) - assets[source] + asset_environment[source] end def rewrite_asset_path(source, dir) if source[0] == ?/ source else - assets.path(source, performing_caching?, dir) + asset_environment.path(source, performing_caching?, dir) end end @@ -98,13 +131,9 @@ module Sprockets end end - def assets - Rails.application.assets - end - # 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.action_controller.present? ? config.action_controller.perform_caching : config.perform_caching end end end diff --git a/actionpack/lib/sprockets/railtie.rb b/actionpack/lib/sprockets/railtie.rb index ab5101f6fc..d1e97c594e 100644 --- a/actionpack/lib/sprockets/railtie.rb +++ b/actionpack/lib/sprockets/railtie.rb @@ -1,16 +1,12 @@ module Sprockets autoload :Helpers, "sprockets/helpers" + # TODO: Get rid of config.assets.enabled class Railtie < ::Rails::Railtie - def self.using_coffee? - require 'coffee-script' - defined?(CoffeeScript) - rescue LoadError - false + rake_tasks do + load "sprockets/assets.rake" end - config.app_generators.javascript_engine :coffee if using_coffee? - # Configure ActionController to use sprockets. initializer "sprockets.set_configs", :after => "action_controller.set_configs" do |app| ActiveSupport.on_load(:action_controller) do |