Browse files

Merge branch 'sprockets'

  • Loading branch information...
2 parents 1b5b53d + a451851 commit f004c8868196f62a6810bc7e693b407fd27a5fa7 @josh josh committed Apr 12, 2011
View
2 Gemfile
@@ -11,6 +11,8 @@ end
gem "rack", :git => "git://github.com/rack/rack.git"
gem "rack-test", :git => "git://github.com/brynary/rack-test.git"
+gem "sprockets", :git => "git://github.com/sstephenson/sprockets.git"
+
gem "rake", ">= 0.8.7"
gem "mocha", ">= 0.9.8"
View
4 actionpack/lib/abstract_controller/asset_paths.rb
@@ -3,7 +3,7 @@ module AssetPaths
extend ActiveSupport::Concern
included do
- config_accessor :asset_host, :asset_path, :assets_dir, :javascripts_dir, :stylesheets_dir
+ config_accessor :asset_host, :asset_path, :assets_dir, :javascripts_dir, :stylesheets_dir, :use_sprockets
end
end
-end
+end
View
1 actionpack/lib/action_controller/railtie.rb
@@ -21,6 +21,7 @@ class Railtie < Rails::Railtie
paths = app.config.paths
options = app.config.action_controller
+ options.use_sprockets ||= app.config.assets.enabled
options.assets_dir ||= paths["public"].first
options.javascripts_dir ||= paths["public/javascripts"].first
options.stylesheets_dir ||= paths["public/stylesheets"].first
View
2 actionpack/lib/action_view/helpers.rb
@@ -22,6 +22,7 @@ module Helpers #:nodoc:
autoload :RecordTagHelper
autoload :SanitizeHelper
autoload :ScriptaculousHelper
+ autoload :SprocketsHelper
autoload :TagHelper
autoload :TextHelper
autoload :TranslationHelper
@@ -52,6 +53,7 @@ module Helpers #:nodoc:
include RecordTagHelper
include SanitizeHelper
include ScriptaculousHelper
+ include SprocketsHelper
include TagHelper
include TextHelper
include TranslationHelper
View
14 actionpack/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb
@@ -86,7 +86,11 @@ def register_javascript_expansion(expansions)
# javascript_path "http://www.railsapplication.com/js/xmlhr" # => http://www.railsapplication.com/js/xmlhr
# javascript_path "http://www.railsapplication.com/js/xmlhr.js" # => http://www.railsapplication.com/js/xmlhr.js
def javascript_path(source)
- asset_paths.compute_public_path(source, 'javascripts', 'js')
+ if config.use_sprockets
+ sprockets_javascript_path(source)
+ else
+ asset_paths.compute_public_path(source, 'javascripts', 'js')
+ end
end
alias_method :path_to_javascript, :javascript_path # aliased to avoid conflicts with a javascript_path named route
@@ -173,8 +177,12 @@ def javascript_path(source)
#
# javascript_include_tag :all, :cache => true, :recursive => true
def javascript_include_tag(*sources)
- @javascript_include ||= JavascriptIncludeTag.new(config, asset_paths)
- @javascript_include.include_tag(*sources)
+ if config.use_sprockets
+ sprockets_javascript_include_tag(*sources)
+ else
+ @javascript_include ||= JavascriptIncludeTag.new(config, asset_paths)
+ @javascript_include.include_tag(*sources)
+ end
end
end
View
14 actionpack/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb
@@ -63,7 +63,11 @@ def register_stylesheet_expansion(expansions)
# stylesheet_path "http://www.railsapplication.com/css/style" # => http://www.railsapplication.com/css/style
# stylesheet_path "http://www.railsapplication.com/css/style.css" # => http://www.railsapplication.com/css/style.css
def stylesheet_path(source)
- asset_paths.compute_public_path(source, 'stylesheets', 'css')
+ if config.use_sprockets
+ sprockets_stylesheet_path(source)
+ else
+ asset_paths.compute_public_path(source, 'stylesheets', 'css')
+ end
end
alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with a stylesheet_path named route
@@ -136,8 +140,12 @@ def stylesheet_path(source)
# stylesheet_link_tag :all, :concat => true
#
def stylesheet_link_tag(*sources)
- @stylesheet_include ||= StylesheetIncludeTag.new(config, asset_paths)
- @stylesheet_include.include_tag(*sources)
+ if config.use_sprockets
+ sprockets_stylesheet_link_tag(*sources)
+ else
+ @stylesheet_include ||= StylesheetIncludeTag.new(config, asset_paths)
+ @stylesheet_include.include_tag(*sources)
+ end
end
end
View
85 actionpack/lib/action_view/helpers/sprockets_helper.rb
@@ -0,0 +1,85 @@
+require 'uri'
+
+module ActionView
+ module Helpers
+ module SprocketsHelper
+ def sprockets_javascript_path(source)
+ compute_sprockets_path source, 'assets', 'js'
+ end
+
+ def sprockets_javascript_include_tag(source, options = {})
+ options = {
+ 'type' => "text/javascript",
+ 'src' => sprockets_javascript_path(source)
+ }.merge(options.stringify_keys)
+
+ content_tag 'script', "", options
+ end
+
+ def sprockets_stylesheet_path(source)
+ compute_sprockets_path source, 'assets', 'css'
+ end
+
+ def sprockets_stylesheet_link_tag(source, options = {})
+ options = {
+ 'rel' => "stylesheet",
+ 'type' => "text/css",
+ 'media' => "screen",
+ 'href' => sprockets_stylesheet_path(source)
+ }.merge(options.stringify_keys)
+
+ tag 'link', options
+ end
+
+ private
+ def compute_sprockets_path(source, dir, default_ext)
+ source = source.to_s
+
+ return source if URI.parse(source).host
+
+ # Add /javscripts to relative paths
+ if source[0] != ?/
+ source = "/#{dir}/#{source}"
+ end
+
+ # Add default extension if there isn't one
+ if default_ext && File.extname(source).empty?
+ source = "#{source}.#{default_ext}"
+ end
+
+ # Fingerprint url
+ if source =~ /^\/#{dir}\/(.+)/
+ source = assets.path($1, config.perform_caching, dir)
+ end
+
+ host = compute_asset_host(source)
+
+ if controller.respond_to?(:request) && host && URI.parse(host).host
+ source = "#{controller.request.protocol}#{host}#{source}"
+ end
+
+ source
+ end
+
+ def compute_asset_host(source)
+ if host = config.asset_host
+ if host.is_a?(Proc) || 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)
+ end
+ else
+ (host =~ /%d/) ? host % (source.hash % 4) : host
+ end
+ end
+ end
+
+ def assets
+ Rails.application.assets
+ end
+ end
+ end
+end
View
0 actionpack/test/fixtures/sprockets/app/javascripts/application.js
No changes.
View
0 actionpack/test/fixtures/sprockets/app/javascripts/dir/xmlhr.js
No changes.
View
0 actionpack/test/fixtures/sprockets/app/javascripts/xmlhr.js
No changes.
View
0 actionpack/test/fixtures/sprockets/app/stylesheets/application.css
No changes.
View
0 actionpack/test/fixtures/sprockets/app/stylesheets/dir/style.css
No changes.
View
0 actionpack/test/fixtures/sprockets/app/stylesheets/style.css
No changes.
View
96 actionpack/test/template/sprockets_helper_test.rb
@@ -0,0 +1,96 @@
+require 'abstract_unit'
+require 'sprockets'
+
+class SprocketsHelperTest < ActionView::TestCase
+ tests ActionView::Helpers::SprocketsHelper
+
+ attr_accessor :assets
+
+ def setup
+ super
+
+ @controller = BasicController.new
+
+ @request = Class.new do
+ def protocol() 'http://' end
+ def ssl?() false end
+ def host_with_port() 'localhost' end
+ end.new
+
+ @controller.request = @request
+
+ @assets = Sprockets::Environment.new
+ @assets.paths << FIXTURES.join("sprockets/app/javascripts")
+ @assets.paths << FIXTURES.join("sprockets/app/stylesheets")
+
+ config.perform_caching = true
+ end
+
+ def url_for(*args)
+ "http://www.example.com"
+ end
+
+ test "javascript path" do
+ assert_equal "/assets/application-d41d8cd98f00b204e9800998ecf8427e.js",
+ sprockets_javascript_path(:application)
+
+ assert_equal "/assets/xmlhr-d41d8cd98f00b204e9800998ecf8427e.js",
+ sprockets_javascript_path("xmlhr")
+ assert_equal "/assets/dir/xmlhr-d41d8cd98f00b204e9800998ecf8427e.js",
+ sprockets_javascript_path("dir/xmlhr.js")
+
+ assert_equal "/dir/xmlhr.js",
+ sprockets_javascript_path("/dir/xmlhr")
+
+ assert_equal "http://www.railsapplication.com/js/xmlhr",
+ sprockets_javascript_path("http://www.railsapplication.com/js/xmlhr")
+ assert_equal "http://www.railsapplication.com/js/xmlhr.js",
+ sprockets_javascript_path("http://www.railsapplication.com/js/xmlhr.js")
+ end
+
+ test "javascript include tag" do
+ assert_equal '<script src="/assets/application-d41d8cd98f00b204e9800998ecf8427e.js" type="text/javascript"></script>',
+ sprockets_javascript_include_tag(:application)
+
+ assert_equal '<script src="/assets/xmlhr-d41d8cd98f00b204e9800998ecf8427e.js" type="text/javascript"></script>',
+ sprockets_javascript_include_tag("xmlhr")
+ assert_equal '<script src="/assets/xmlhr-d41d8cd98f00b204e9800998ecf8427e.js" type="text/javascript"></script>',
+ sprockets_javascript_include_tag("xmlhr.js")
+ assert_equal '<script src="http://www.railsapplication.com/xmlhr" type="text/javascript"></script>',
+ sprockets_javascript_include_tag("http://www.railsapplication.com/xmlhr")
+ end
+
+ test "stylesheet path" do
+ assert_equal "/assets/application-d41d8cd98f00b204e9800998ecf8427e.css",
+ sprockets_stylesheet_path(:application)
+
+ assert_equal "/assets/style-d41d8cd98f00b204e9800998ecf8427e.css",
+ sprockets_stylesheet_path("style")
+ assert_equal "/assets/dir/style-d41d8cd98f00b204e9800998ecf8427e.css",
+ sprockets_stylesheet_path("dir/style.css")
+ assert_equal "/dir/style.css",
+ sprockets_stylesheet_path("/dir/style.css")
+
+ assert_equal "http://www.railsapplication.com/css/style",
+ sprockets_stylesheet_path("http://www.railsapplication.com/css/style")
+ assert_equal "http://www.railsapplication.com/css/style.css",
+ sprockets_stylesheet_path("http://www.railsapplication.com/css/style.css")
+ end
+
+ test "stylesheet link tag" do
+ assert_equal '<link href="/assets/application-d41d8cd98f00b204e9800998ecf8427e.css" media="screen" rel="stylesheet" type="text/css" />',
+ sprockets_stylesheet_link_tag(:application)
+
+ assert_equal '<link href="/assets/style-d41d8cd98f00b204e9800998ecf8427e.css" media="screen" rel="stylesheet" type="text/css" />',
+ sprockets_stylesheet_link_tag("style")
+ assert_equal '<link href="/assets/style-d41d8cd98f00b204e9800998ecf8427e.css" media="screen" rel="stylesheet" type="text/css" />',
+ sprockets_stylesheet_link_tag("style.css")
+
+ assert_equal '<link href="http://www.railsapplication.com/style.css" media="screen" rel="stylesheet" type="text/css" />',
+ sprockets_stylesheet_link_tag("http://www.railsapplication.com/style.css")
+ assert_equal '<link href="/assets/style-d41d8cd98f00b204e9800998ecf8427e.css" media="all" rel="stylesheet" type="text/css" />',
+ sprockets_stylesheet_link_tag("style", :media => "all")
+ assert_equal '<link href="/assets/style-d41d8cd98f00b204e9800998ecf8427e.css" media="print" rel="stylesheet" type="text/css" />',
+ sprockets_stylesheet_link_tag("style", :media => "print")
+ end
+end
View
32 railties/lib/rails/application.rb
@@ -137,6 +137,38 @@ def config
@config ||= Application::Configuration.new(find_root_with_flag("config.ru", Dir.pwd))
end
+ def assets
+ @assets ||= build_asset_environment
+ end
+ attr_writer :assets
+
+ def build_asset_environment
+ return unless config.assets.enabled
+ require 'sprockets'
+ env = Sprockets::Environment.new(root.to_s)
+ env.static_root = File.join(root.join("public"), config.assets.prefix)
+ env
+ end
+
+ initializer :add_sprockets_paths do |app|
+ if config.assets.enabled
+ paths = [
+ "app/javascripts",
+ "app/stylesheets",
+ "vendor/plugins/*/app/javascripts",
+ "vendor/plugins/*/app/stylesheets",
+ "vendor/plugins/*/javascripts",
+ "vendor/plugins/*/stylesheets"
+ ] + config.assets.paths
+
+ paths.each do |pattern|
+ Dir[app.root.join(pattern)].each do |dir|
+ app.assets.paths << dir
+ end
+ end
+ end
+ end
+
protected
def default_asset_path
View
9 railties/lib/rails/application/configuration.rb
@@ -9,7 +9,8 @@ class Configuration < ::Rails::Engine::Configuration
:filter_parameters, :helpers_paths, :logger,
:preload_frameworks, :reload_plugins,
:secret_token, :serve_static_assets, :session_options,
- :time_zone, :whiny_nils, :force_ssl
+ :time_zone, :whiny_nils, :force_ssl,
+ :assets
attr_writer :log_level
@@ -29,6 +30,12 @@ def initialize(*)
@log_level = nil
@middleware = app_middleware
@generators = app_generators
+
+ @assets = ActiveSupport::OrderedOptions.new
+ @assets.enabled = false
+ @assets.paths = []
+ @assets.precompile = []
+ @assets.prefix = "/assets"
end
def compiled_asset_path
View
21 railties/lib/rails/application/finisher.rb
@@ -33,6 +33,27 @@ module Finisher
end
end
+ initializer :add_sprockets_route do |app|
+ assets = config.assets
+ if assets.enabled
+ app.routes.append do
+ mount app.assets => assets.prefix
+ end
+ end
+ end
+
+ initializer :set_sprockets_logger do |app|
+ if config.assets.enabled
+ app.assets.logger = Rails.logger
+ end
+ end
+
+ initializer :index_sprockets_environment do |app|
+ if config.assets.enabled && config.action_controller.perform_caching
+ app.assets = app.assets.index
+ end
+ end
+
initializer :build_middleware_stack do
build_middleware_stack
end
View
1 railties/lib/rails/tasks.rb
@@ -3,6 +3,7 @@
# Load Rails rakefile extensions
%w(
annotations
+ assets
documentation
framework
log
View
6 railties/lib/rails/tasks/assets.rake
@@ -0,0 +1,6 @@
+namespace :assets do
+ task :compile => :environment do
+ assets = Rails.application.config.assets.precompile
+ Rails.application.assets.precompile(*assets)
+ end
+end

3 comments on commit f004c88

@josevalim
Ruby on Rails member

Great! There are some things to tidy up:

1) Will sprockets be an ActionPack dependency? If so, we should not forget at some point to add it as a dependency to the gemspec.
2) We need railties tests to ensure the full stack work, including rake tasks.
3) This currently won't work with engines at all. Just plugins inside vendor/plugins. This is a step backward to the direction we are moving lately (more gems, less plugins). Using the engines paths API should fix that. I have written comments on the previous branch before the merge, do you still have them? It seems they are long gone and I don't remember all changes anymore! :(
4) We need documentation.

@dhh
Ruby on Rails member

@josevalim, can you help clean some of these things up? Especially around the engines stuff. That'd be great. Sprockets is definitely an ActionPack dependency, so as soon as there's a final release to go with this, we'll move it in there.

@josevalim
Ruby on Rails member

@dhh I can help cleaning some of these things up, but first we need to at least have full stack (railties) tests to ensure I won't screw something up in the process.

Please sign in to comment.