`rake assets:precompile` loads the application but does not initialize it.

To the app developer, this means configuration add in
config/initializers/* will not be executed.

Plugins developers need to special case their initializers that are
meant to be run in the assets group by adding :group => :assets.

Conflicts:

	railties/CHANGELOG
	railties/test/application/assets_test.rb
This commit is contained in:
José Valim 2011-09-24 01:56:49 +02:00
parent 096717e6f7
commit eb367afeed
11 changed files with 183 additions and 110 deletions

View File

@ -11,8 +11,9 @@ namespace :assets do
ENV["RAILS_ENV"] ||= "production"
Kernel.exec $0, *ARGV
else
Rake::Task["environment"].invoke
Rake::Task["tmp:cache:clear"].invoke
Rails.application.initialize!(:assets)
Sprockets::Bootstrap.new(Rails.application).run
# Ensure that action view is loaded and the appropriate sprockets hooks get executed
ActionView::Base

View File

@ -0,0 +1,65 @@
module Sprockets
class Bootstrap
def initialize(app)
@app = app
end
# TODO: Get rid of config.assets.enabled
def run
app, config = @app, @app.config
return unless app.assets
config.assets.paths.each { |path| app.assets.append_path(path) }
if config.assets.compress
# temporarily hardcode default JS compressor to uglify. Soon, it will work
# the same as SCSS, where a default plugin sets the default.
unless config.assets.js_compressor == false
app.assets.js_compressor = LazyCompressor.new { expand_js_compressor(config.assets.js_compressor || :uglifier) }
end
unless config.assets.css_compressor == false
app.assets.css_compressor = LazyCompressor.new { expand_css_compressor(config.assets.css_compressor) }
end
end
if config.assets.compile
app.routes.prepend do
mount app.assets => config.assets.prefix
end
end
if config.assets.digest
app.assets = app.assets.index
end
end
protected
def expand_js_compressor(sym)
case sym
when :closure
require 'closure-compiler'
Closure::Compiler.new
when :uglifier
require 'uglifier'
Uglifier.new
when :yui
require 'yui/compressor'
YUI::JavaScriptCompressor.new
else
sym
end
end
def expand_css_compressor(sym)
case sym
when :yui
require 'yui/compressor'
YUI::CssCompressor.new
else
sym
end
end
end
end

View File

@ -1,5 +1,6 @@
module Sprockets
autoload :Helpers, "sprockets/helpers"
autoload :Bootstrap, "sprockets/bootstrap"
autoload :Helpers, "sprockets/helpers"
autoload :LazyCompressor, "sprockets/compressors"
autoload :NullCompressor, "sprockets/compressors"
autoload :StaticCompiler, "sprockets/static_compiler"
@ -12,7 +13,7 @@ module Sprockets
load "sprockets/assets.rake"
end
initializer "sprockets.environment" do |app|
initializer "sprockets.environment", :group => :assets do |app|
config = app.config
next unless config.assets.enabled
@ -51,59 +52,7 @@ module Sprockets
# are compiled, and so that other Railties have an opportunity to
# register compressors.
config.after_initialize do |app|
next unless app.assets
config = app.config
config.assets.paths.each { |path| app.assets.append_path(path) }
if config.assets.compress
# temporarily hardcode default JS compressor to uglify. Soon, it will work
# the same as SCSS, where a default plugin sets the default.
unless config.assets.js_compressor == false
app.assets.js_compressor = LazyCompressor.new { expand_js_compressor(config.assets.js_compressor || :uglifier) }
end
unless config.assets.css_compressor == false
app.assets.css_compressor = LazyCompressor.new { expand_css_compressor(config.assets.css_compressor) }
end
end
if config.assets.compile
app.routes.prepend do
mount app.assets => config.assets.prefix
end
end
if config.assets.digest
app.assets = app.assets.index
end
Sprockets::Bootstrap.new(app).run
end
protected
def expand_js_compressor(sym)
case sym
when :closure
require 'closure-compiler'
Closure::Compiler.new
when :uglifier
require 'uglifier'
Uglifier.new
when :yui
require 'yui/compressor'
YUI::JavaScriptCompressor.new
else
sym
end
end
def expand_css_compressor(sym)
case sym
when :yui
require 'yui/compressor'
YUI::CssCompressor.new
else
sym
end
end
end
end

View File

@ -10,6 +10,18 @@
* Removed old 'config.paths.app.controller' API in favor of 'config.paths["app/controller"]' API. [Guillermo Iguaran]
*Rails 3.1.1
* `rake assets:precompile` loads the application but does not initialize it.
To the app developer, this means configuration add in
config/initializers/* will not be executed.
Plugins developers need to special case their initializers that are
meant to be run in the assets group by adding :group => :assets.
*Rails 3.1.0 (August 30, 2011)*
* The default database schema file is written as UTF-8. [Aaron Patterson]

View File

@ -83,7 +83,6 @@ module Rails
require environment if environment
end
def reload_routes!
routes_reloader.reload!
end
@ -92,9 +91,9 @@ module Rails
@routes_reloader ||= RoutesReloader.new
end
def initialize!
def initialize!(group=nil)
raise "Application has been already initialized." if @initialized
run_initializers(self)
run_initializers(group, self)
@initialized = true
self
end

View File

@ -7,21 +7,21 @@ module Rails
module Bootstrap
include Initializable
initializer :load_environment_hook do end
initializer :load_environment_hook, :group => :all do end
initializer :load_active_support do
initializer :load_active_support, :group => :all do
require "active_support/all" unless config.active_support.bare
end
# Preload all frameworks specified by the Configuration#frameworks.
# Used by Passenger to ensure everything's loaded before forking and
# to avoid autoload race conditions in JRuby.
initializer :preload_frameworks do
initializer :preload_frameworks, :group => :all do
ActiveSupport::Autoload.eager_autoload! if config.preload_frameworks
end
# Initialize the logger early in the stack in case we need to log some deprecation.
initializer :initialize_logger do
initializer :initialize_logger, :group => :all do
Rails.logger ||= config.logger || begin
path = config.paths["log"].first
logger = ActiveSupport::BufferedLogger.new(path)
@ -41,7 +41,7 @@ module Rails
end
# Initialize cache early in the stack so railties can make use of it.
initializer :initialize_cache do
initializer :initialize_cache, :group => :all do
unless defined?(RAILS_CACHE)
silence_warnings { Object.const_set "RAILS_CACHE", ActiveSupport::Cache.lookup_store(config.cache_store) }
@ -51,7 +51,7 @@ module Rails
end
end
initializer :set_clear_dependencies_hook do
initializer :set_clear_dependencies_hook, :group => :all do
ActionDispatch::Reloader.to_cleanup do
ActiveSupport::DescendantsTracker.clear
ActiveSupport::Dependencies.clear
@ -60,11 +60,11 @@ module Rails
# Sets the dependency loading mechanism.
# TODO: Remove files from the $" and always use require.
initializer :initialize_dependency_mechanism do
initializer :initialize_dependency_mechanism, :group => :all do
ActiveSupport::Dependencies.mechanism = config.cache_classes ? :require : :load
end
initializer :bootstrap_hook do |app|
initializer :bootstrap_hook, :group => :all do |app|
ActiveSupport.run_load_hooks(:before_initialize, app)
end
end

View File

@ -537,12 +537,12 @@ module Rails
end
end
initializer :load_environment_config, :before => :load_environment_hook do
initializer :load_environment_config, :before => :load_environment_hook, :group => :all do
environment = paths["config/environments"].existent.first
require environment if environment
end
initializer :append_assets_path do |app|
initializer :append_assets_path, :group => :assets do |app|
app.config.assets.paths.unshift(*paths["vendor/assets"].existent_directories)
app.config.assets.paths.unshift(*paths["lib/assets"].existent_directories)
app.config.assets.paths.unshift(*paths["app/assets"].existent_directories)

View File

@ -21,6 +21,10 @@ module Rails
@options[:after]
end
def belongs_to?(group)
@options[:group] == group || @options[:group] == :all
end
def run(*args)
@context.instance_exec(*args, &block)
end
@ -44,10 +48,10 @@ module Rails
end
end
def run_initializers(*args)
def run_initializers(group=nil, *args)
return if instance_variable_defined?(:@ran)
initializers.tsort.each do |initializer|
initializer.run(*args)
initializer.run(*args) if group.nil? || initializer.belongs_to?(group)
end
@ran = true
end

View File

@ -21,6 +21,12 @@ module ApplicationTests
@app ||= Rails.application
end
def precompile!
capture(:stdout) do
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
end
test "assets routes have higher priority" do
app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();"
@ -38,7 +44,7 @@ module ApplicationTests
test "assets do not require compressors until it is used" do
app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();"
app_file "config/initializers/compile.rb", "Rails.application.config.assets.compile = true"
add_to_env_config "production", "config.assets.compile = true"
ENV["RAILS_ENV"] = "production"
require "#{app_path}/config/environment"
@ -54,9 +60,8 @@ module ApplicationTests
app_file "app/assets/javascripts/foo/application.js", "alert();"
ENV["RAILS_ENV"] = nil
capture(:stdout) do
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
precompile!
files = Dir["#{app_path}/public/assets/application-*.js"]
files << Dir["#{app_path}/public/assets/foo/application-*.js"].first
files.each do |file|
@ -80,13 +85,12 @@ module ApplicationTests
"happy.happy.face.png", "happy", "happy.face", "-happyface",
"-happy.png", "-happy.face.png", "_happyface", "_happy.face.png",
"_happy.png"]
images_should_compile.each do |filename|
app_file "app/assets/images/#{filename}", "happy"
end
capture(:stdout) do
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
precompile!
images_should_compile.each do |filename|
assert File.exists?("#{app_path}/public/assets/#{filename}")
@ -103,11 +107,12 @@ module ApplicationTests
end
test "precompile sets flag notifying rails its precompiling" do
compile = <<COMPILE
raise "ENV RAILS_ASSETS_PRECOMPILE not set" unless ENV["RAILS_ASSETS_PRECOMPILE"]
COMPILE
app_file "config/initializers/compile.rb", compile
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
add_to_config = <<-RUBY
initializer :check_assets_precompile, :group => :assets do
raise "ENV RAILS_ASSETS_PRECOMPILE not set" unless ENV["RAILS_ASSETS_PRECOMPILE"]
end
RUBY
precompile!
assert $?.success?
end
@ -127,9 +132,7 @@ COMPILE
# digest is default in false, we must enable it for test environment
add_to_config "config.assets.digest = true"
capture(:stdout) do
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
precompile!
manifest = "#{app_path}/public/assets/manifest.yml"
@ -146,9 +149,7 @@ COMPILE
add_to_config "config.assets.manifest = '#{app_path}/shared'"
FileUtils.mkdir "#{app_path}/shared"
capture(:stdout) do
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
precompile!
manifest = "#{app_path}/shared/manifest.yml"
@ -164,9 +165,7 @@ COMPILE
add_to_config "config.assets.digest = true"
add_to_config "config.assets.prefix = '/x'"
capture(:stdout) do
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
precompile!
manifest = "#{app_path}/public/x/manifest.yml"
assets = YAML.load_file(manifest)
@ -178,9 +177,7 @@ COMPILE
app_file "app/assets/javascripts/application.js", "alert();"
add_to_config "config.assets.digest = false"
capture(:stdout) do
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
precompile!
assert File.exists?("#{app_path}/public/assets/application.js")
assert File.exists?("#{app_path}/public/assets/application.css")
@ -194,12 +191,11 @@ COMPILE
test "assets do not require any assets group gem when manifest file is present" do
app_file "app/assets/javascripts/application.js", "alert();"
app_file "config/initializers/serve_static_assets.rb", "Rails.application.config.serve_static_assets = true"
add_to_env_config "production", "config.serve_static_assets = true"
ENV["RAILS_ENV"] = "production"
capture(:stdout) do
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
precompile!
manifest = "#{app_path}/public/assets/manifest.yml"
assets = YAML.load_file(manifest)
asset_path = assets["application.js"]
@ -223,9 +219,7 @@ COMPILE
RUBY
ENV["RAILS_ENV"] = "production"
capture(:stdout) do
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
precompile!
# Create file after of precompile
app_file "app/assets/javascripts/app.js", "alert();"
@ -249,9 +243,7 @@ COMPILE
RUBY
ENV["RAILS_ENV"] = "development"
capture(:stdout) do
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
precompile!
# Create file after of precompile
app_file "app/assets/javascripts/app.js", "alert();"
@ -292,10 +284,7 @@ COMPILE
app_file "app/assets/images/レイルズ.png", "not a image really"
add_to_config "config.assets.precompile = [ /\.png$$/, /application.(css|js)$/ ]"
capture(:stdout) do
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
precompile!
assert File.exists?("#{app_path}/public/assets/レイルズ.png")
manifest = "#{app_path}/public/assets/manifest.yml"
@ -367,5 +356,50 @@ COMPILE
assert_match "alert();", last_response.body
assert_equal 200, last_response.status
end
test "assets are concatenated when debug is off and compile is off either if debug_assets param is provided" do
app_with_assets_in_view
# config.assets.debug and config.assets.compile are false for production environment
ENV["RAILS_ENV"] = "production"
precompile!
require "#{app_path}/config/environment"
class ::PostsController < ActionController::Base ; end
# the debug_assets params isn't used if compile is off
get '/posts?debug_assets=true'
assert_match(/<script src="\/assets\/application-([0-z]+)\.js" type="text\/javascript"><\/script>/, last_response.body)
assert_no_match(/<script src="\/assets\/xmlhr-([0-z]+)\.js" type="text\/javascript"><\/script>/, last_response.body)
end
test "assets aren't concatened when compile is true is on and debug_assets params is true" do
app_with_assets_in_view
add_to_env_config "production", "config.assets.compile = true"
add_to_env_config "production", "config.assets.allow_debugging = true"
ENV["RAILS_ENV"] = "production"
require "#{app_path}/config/environment"
class ::PostsController < ActionController::Base ; end
get '/posts?debug_assets=true'
assert_match(/<script src="\/assets\/application-([0-z]+)\.js\?body=1" type="text\/javascript"><\/script>/, last_response.body)
assert_match(/<script src="\/assets\/xmlhr-([0-z]+)\.js\?body=1" type="text\/javascript"><\/script>/, last_response.body)
end
private
def app_with_assets_in_view
app_file "app/assets/javascripts/application.js", "//= require_tree ."
app_file "app/assets/javascripts/xmlhr.js", "function f1() { alert(); }"
app_file "app/views/posts/index.html.erb", "<%= javascript_include_tag 'application' %>"
app_file "config/routes.rb", <<-RUBY
AppTemplate::Application.routes.draw do
match '/posts', :to => "posts#index"
end
RUBY
end
end
end

View File

@ -216,7 +216,7 @@ module InitializableTests
class WithArgsTest < ActiveSupport::TestCase
test "running initializers with args" do
$with_arg = nil
WithArgs.new.run_initializers('foo')
WithArgs.new.run_initializers(nil, 'foo')
assert_equal 'foo', $with_arg
end
end

View File

@ -224,6 +224,15 @@ module TestHelpers
end
end
def add_to_env_config(env, str)
environment = File.read("#{app_path}/config/environments/#{env}.rb")
if environment =~ /(\n\s*end\s*)\Z/
File.open("#{app_path}/config/environments/#{env}.rb", 'w') do |f|
f.puts $` + "\n#{str}\n" + $1
end
end
end
def remove_from_config(str)
file = "#{app_path}/config/application.rb"
contents = File.read(file)