1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

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" ENV["RAILS_ENV"] ||= "production"
Kernel.exec $0, *ARGV Kernel.exec $0, *ARGV
else else
Rake::Task["environment"].invoke
Rake::Task["tmp:cache:clear"].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 # Ensure that action view is loaded and the appropriate sprockets hooks get executed
ActionView::Base 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,4 +1,5 @@
module Sprockets module Sprockets
autoload :Bootstrap, "sprockets/bootstrap"
autoload :Helpers, "sprockets/helpers" autoload :Helpers, "sprockets/helpers"
autoload :LazyCompressor, "sprockets/compressors" autoload :LazyCompressor, "sprockets/compressors"
autoload :NullCompressor, "sprockets/compressors" autoload :NullCompressor, "sprockets/compressors"
@ -12,7 +13,7 @@ module Sprockets
load "sprockets/assets.rake" load "sprockets/assets.rake"
end end
initializer "sprockets.environment" do |app| initializer "sprockets.environment", :group => :assets do |app|
config = app.config config = app.config
next unless config.assets.enabled next unless config.assets.enabled
@ -51,59 +52,7 @@ module Sprockets
# are compiled, and so that other Railties have an opportunity to # are compiled, and so that other Railties have an opportunity to
# register compressors. # register compressors.
config.after_initialize do |app| config.after_initialize do |app|
next unless app.assets Sprockets::Bootstrap.new(app).run
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
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 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] * 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)* *Rails 3.1.0 (August 30, 2011)*
* The default database schema file is written as UTF-8. [Aaron Patterson] * The default database schema file is written as UTF-8. [Aaron Patterson]

View file

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

View file

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

View file

@ -537,12 +537,12 @@ module Rails
end end
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 environment = paths["config/environments"].existent.first
require environment if environment require environment if environment
end 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["vendor/assets"].existent_directories)
app.config.assets.paths.unshift(*paths["lib/assets"].existent_directories) app.config.assets.paths.unshift(*paths["lib/assets"].existent_directories)
app.config.assets.paths.unshift(*paths["app/assets"].existent_directories) app.config.assets.paths.unshift(*paths["app/assets"].existent_directories)

View file

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

View file

@ -21,6 +21,12 @@ module ApplicationTests
@app ||= Rails.application @app ||= Rails.application
end end
def precompile!
capture(:stdout) do
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
end
test "assets routes have higher priority" do test "assets routes have higher priority" do
app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();" 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 test "assets do not require compressors until it is used" do
app_file "app/assets/javascripts/demo.js.erb", "<%= :alert %>();" 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" ENV["RAILS_ENV"] = "production"
require "#{app_path}/config/environment" require "#{app_path}/config/environment"
@ -54,9 +60,8 @@ module ApplicationTests
app_file "app/assets/javascripts/foo/application.js", "alert();" app_file "app/assets/javascripts/foo/application.js", "alert();"
ENV["RAILS_ENV"] = nil ENV["RAILS_ENV"] = nil
capture(:stdout) do precompile!
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
files = Dir["#{app_path}/public/assets/application-*.js"] files = Dir["#{app_path}/public/assets/application-*.js"]
files << Dir["#{app_path}/public/assets/foo/application-*.js"].first files << Dir["#{app_path}/public/assets/foo/application-*.js"].first
files.each do |file| files.each do |file|
@ -80,13 +85,12 @@ module ApplicationTests
"happy.happy.face.png", "happy", "happy.face", "-happyface", "happy.happy.face.png", "happy", "happy.face", "-happyface",
"-happy.png", "-happy.face.png", "_happyface", "_happy.face.png", "-happy.png", "-happy.face.png", "_happyface", "_happy.face.png",
"_happy.png"] "_happy.png"]
images_should_compile.each do |filename| images_should_compile.each do |filename|
app_file "app/assets/images/#{filename}", "happy" app_file "app/assets/images/#{filename}", "happy"
end end
capture(:stdout) do precompile!
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
images_should_compile.each do |filename| images_should_compile.each do |filename|
assert File.exists?("#{app_path}/public/assets/#{filename}") assert File.exists?("#{app_path}/public/assets/#{filename}")
@ -103,11 +107,12 @@ module ApplicationTests
end end
test "precompile sets flag notifying rails its precompiling" do test "precompile sets flag notifying rails its precompiling" do
compile = <<COMPILE add_to_config = <<-RUBY
initializer :check_assets_precompile, :group => :assets do
raise "ENV RAILS_ASSETS_PRECOMPILE not set" unless ENV["RAILS_ASSETS_PRECOMPILE"] raise "ENV RAILS_ASSETS_PRECOMPILE not set" unless ENV["RAILS_ASSETS_PRECOMPILE"]
COMPILE end
app_file "config/initializers/compile.rb", compile RUBY
Dir.chdir(app_path){ `bundle exec rake assets:precompile` } precompile!
assert $?.success? assert $?.success?
end end
@ -127,9 +132,7 @@ COMPILE
# digest is default in false, we must enable it for test environment # digest is default in false, we must enable it for test environment
add_to_config "config.assets.digest = true" add_to_config "config.assets.digest = true"
capture(:stdout) do precompile!
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
manifest = "#{app_path}/public/assets/manifest.yml" manifest = "#{app_path}/public/assets/manifest.yml"
@ -146,9 +149,7 @@ COMPILE
add_to_config "config.assets.manifest = '#{app_path}/shared'" add_to_config "config.assets.manifest = '#{app_path}/shared'"
FileUtils.mkdir "#{app_path}/shared" FileUtils.mkdir "#{app_path}/shared"
capture(:stdout) do precompile!
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
manifest = "#{app_path}/shared/manifest.yml" manifest = "#{app_path}/shared/manifest.yml"
@ -164,9 +165,7 @@ COMPILE
add_to_config "config.assets.digest = true" add_to_config "config.assets.digest = true"
add_to_config "config.assets.prefix = '/x'" add_to_config "config.assets.prefix = '/x'"
capture(:stdout) do precompile!
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
manifest = "#{app_path}/public/x/manifest.yml" manifest = "#{app_path}/public/x/manifest.yml"
assets = YAML.load_file(manifest) assets = YAML.load_file(manifest)
@ -178,9 +177,7 @@ COMPILE
app_file "app/assets/javascripts/application.js", "alert();" app_file "app/assets/javascripts/application.js", "alert();"
add_to_config "config.assets.digest = false" add_to_config "config.assets.digest = false"
capture(:stdout) do precompile!
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
assert File.exists?("#{app_path}/public/assets/application.js") assert File.exists?("#{app_path}/public/assets/application.js")
assert File.exists?("#{app_path}/public/assets/application.css") 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 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 "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" ENV["RAILS_ENV"] = "production"
capture(:stdout) do precompile!
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
manifest = "#{app_path}/public/assets/manifest.yml" manifest = "#{app_path}/public/assets/manifest.yml"
assets = YAML.load_file(manifest) assets = YAML.load_file(manifest)
asset_path = assets["application.js"] asset_path = assets["application.js"]
@ -223,9 +219,7 @@ COMPILE
RUBY RUBY
ENV["RAILS_ENV"] = "production" ENV["RAILS_ENV"] = "production"
capture(:stdout) do precompile!
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
# Create file after of precompile # Create file after of precompile
app_file "app/assets/javascripts/app.js", "alert();" app_file "app/assets/javascripts/app.js", "alert();"
@ -249,9 +243,7 @@ COMPILE
RUBY RUBY
ENV["RAILS_ENV"] = "development" ENV["RAILS_ENV"] = "development"
capture(:stdout) do precompile!
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
# Create file after of precompile # Create file after of precompile
app_file "app/assets/javascripts/app.js", "alert();" app_file "app/assets/javascripts/app.js", "alert();"
@ -292,10 +284,7 @@ COMPILE
app_file "app/assets/images/レイルズ.png", "not a image really" app_file "app/assets/images/レイルズ.png", "not a image really"
add_to_config "config.assets.precompile = [ /\.png$$/, /application.(css|js)$/ ]" add_to_config "config.assets.precompile = [ /\.png$$/, /application.(css|js)$/ ]"
capture(:stdout) do precompile!
Dir.chdir(app_path){ `bundle exec rake assets:precompile` }
end
assert File.exists?("#{app_path}/public/assets/レイルズ.png") assert File.exists?("#{app_path}/public/assets/レイルズ.png")
manifest = "#{app_path}/public/assets/manifest.yml" manifest = "#{app_path}/public/assets/manifest.yml"
@ -367,5 +356,50 @@ COMPILE
assert_match "alert();", last_response.body assert_match "alert();", last_response.body
assert_equal 200, last_response.status assert_equal 200, last_response.status
end 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
end end

View file

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

View file

@ -224,6 +224,15 @@ module TestHelpers
end end
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) def remove_from_config(str)
file = "#{app_path}/config/application.rb" file = "#{app_path}/config/application.rb"
contents = File.read(file) contents = File.read(file)