aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/lib/active_record/railtie.rb17
-rw-r--r--activesupport/lib/active_support/lazy_load_hooks.rb18
-rw-r--r--activesupport/test/lazy_load_hooks_test.rb67
-rw-r--r--railties/guides/source/initialization.textile2
-rw-r--r--railties/lib/rails/application.rb10
-rw-r--r--railties/lib/rails/application/bootstrap.rb8
-rw-r--r--railties/lib/rails/application/configuration.rb2
-rw-r--r--railties/lib/rails/application/finisher.rb6
-rw-r--r--railties/lib/rails/engine.rb15
-rw-r--r--railties/lib/rails/railtie/configuration.rb48
-rw-r--r--railties/test/application/initializers/initializers_test.rb13
11 files changed, 154 insertions, 52 deletions
diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb
index 898df0a67a..a32fb7d399 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -15,6 +15,12 @@ module ActiveRecord
config.generators.orm :active_record, :migration => true,
:timestamps => true
+ config.app_middleware.insert_after "::ActionDispatch::Callbacks",
+ "ActiveRecord::QueryCache"
+
+ config.app_middleware.insert_after "::ActionDispatch::Callbacks",
+ "ActiveRecord::ConnectionAdapters::ConnectionManagement"
+
rake_tasks do
load "active_record/railties/databases.rake"
end
@@ -58,16 +64,9 @@ module ActiveRecord
end
end
- # Setup database middleware after initializers have run
- initializer "active_record.initialize_database_middleware", :after => "action_controller.set_configs" do |app|
- middleware = app.config.middleware
- middleware.insert_after "::ActionDispatch::Callbacks", ActiveRecord::QueryCache
- middleware.insert_after "::ActionDispatch::Callbacks", ActiveRecord::ConnectionAdapters::ConnectionManagement
- end
-
initializer "active_record.set_dispatch_hooks", :before => :set_clear_dependencies_hook do |app|
- ActiveSupport.on_load(:active_record) do
- unless app.config.cache_classes
+ unless app.config.cache_classes
+ ActiveSupport.on_load(:active_record) do
ActionDispatch::Callbacks.after do
ActiveRecord::Base.reset_subclasses
ActiveRecord::Base.clear_reloadable_connections!
diff --git a/activesupport/lib/active_support/lazy_load_hooks.rb b/activesupport/lib/active_support/lazy_load_hooks.rb
index 642a4c105c..3664431a28 100644
--- a/activesupport/lib/active_support/lazy_load_hooks.rb
+++ b/activesupport/lib/active_support/lazy_load_hooks.rb
@@ -2,16 +2,26 @@ module ActiveSupport
@load_hooks = Hash.new {|h,k| h[k] = [] }
@loaded = {}
- def self.on_load(name, &block)
+ def self.on_load(name, options = {}, &block)
if base = @loaded[name]
- base.instance_eval(&block)
+ execute_hook(base, options, block)
else
- @load_hooks[name] << block
+ @load_hooks[name] << [block, options]
+ end
+ end
+
+ def self.execute_hook(base, options, block)
+ if options[:yield]
+ block.call(base)
+ else
+ base.instance_eval(&block)
end
end
def self.run_load_hooks(name, base = Object)
- @load_hooks[name].each { |hook| base.instance_eval(&hook) }
@loaded[name] = base
+ @load_hooks[name].each do |hook, options|
+ execute_hook(base, options, hook)
+ end
end
end \ No newline at end of file
diff --git a/activesupport/test/lazy_load_hooks_test.rb b/activesupport/test/lazy_load_hooks_test.rb
new file mode 100644
index 0000000000..58ccc14324
--- /dev/null
+++ b/activesupport/test/lazy_load_hooks_test.rb
@@ -0,0 +1,67 @@
+require 'abstract_unit'
+
+class LazyLoadHooksTest < ActiveSupport::TestCase
+ def test_basic_hook
+ i = 0
+ ActiveSupport.on_load(:basic_hook) { i += 1 }
+ ActiveSupport.run_load_hooks(:basic_hook)
+ assert_equal 1, i
+ end
+
+ def test_hook_registered_after_run
+ i = 0
+ ActiveSupport.run_load_hooks(:registered_after)
+ assert_equal 0, i
+ ActiveSupport.on_load(:registered_after) { i += 1 }
+ assert_equal 1, i
+ end
+
+ def test_hook_receives_a_context
+ i = 0
+ ActiveSupport.on_load(:contextual) { i += incr }
+ assert_equal 0, i
+ ActiveSupport.run_load_hooks(:contextual, FakeContext.new(2))
+ assert_equal 2, i
+ end
+
+ def test_hook_receives_a_context_afterward
+ i = 0
+ ActiveSupport.run_load_hooks(:contextual_after, FakeContext.new(2))
+ assert_equal 0, i
+ ActiveSupport.on_load(:contextual_after) { i += incr }
+ assert_equal 2, i
+ end
+
+ def test_hook_with_yield_true
+ i = 0
+ ActiveSupport.on_load(:contextual_yield, :yield => true) do |obj|
+ i += obj.incr + incr_amt
+ end
+ assert_equal 0, i
+ ActiveSupport.run_load_hooks(:contextual_yield, FakeContext.new(2))
+ assert_equal 7, i
+ end
+
+ def test_hook_with_yield_true_afterward
+ i = 0
+ ActiveSupport.run_load_hooks(:contextual_yield_after, FakeContext.new(2))
+ assert_equal 0, i
+ ActiveSupport.on_load(:contextual_yield_after, :yield => true) do |obj|
+ i += obj.incr + incr_amt
+ end
+ assert_equal 7, i
+ end
+
+private
+
+ def incr_amt
+ 5
+ end
+
+ class FakeContext
+ attr_reader :incr
+ def initialize(incr)
+ @incr = incr
+ end
+ end
+end \ No newline at end of file
diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile
index 9ce27fa331..96d6998e1c 100644
--- a/railties/guides/source/initialization.textile
+++ b/railties/guides/source/initialization.textile
@@ -2379,7 +2379,6 @@ Now that we've referenced that class, it will be required for us. You'll notice
* initialize_subscriber
* set_clear_dependencies_hook
* initialize_dependency_mechanism
-* bootstrap_load_path
These are all defined using the +initializer+ method:
@@ -2930,7 +2929,6 @@ With +@@autoloads+ being
* initialize_subscriber
* set_clear_dependencies_hook
* initialize_dependency_mechanism
-* bootstrap_load_path
h4. Active Support Initializers
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index d39f9a2ae9..9e18dccf69 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -12,7 +12,7 @@ module Rails
# points to it.
#
# In other words, Rails::Application is Singleton and whenever you are accessing
- # Rails::Application.config or YourApplication::Application.config, you are actually
+ # Rails::Application.config or YourApplication::Application.config, you are actually
# accessing YourApplication::Application.instance.config.
#
# == Initialization
@@ -40,7 +40,7 @@ module Rails
#
# The Application is also responsible for building the middleware stack and setting up
# both application and engines metals.
- #
+ #
class Application < Engine
autoload :Bootstrap, 'rails/application/bootstrap'
autoload :Configurable, 'rails/application/configurable'
@@ -69,6 +69,8 @@ module Rails
raise "You cannot have more than one Rails::Application" if Rails.application
super
Rails.application = base.instance
+
+ ActiveSupport.run_load_hooks(:before_configuration, base.instance)
end
def respond_to?(*args)
@@ -82,7 +84,7 @@ module Rails
end
end
- delegate :metal_loader, :to => :config
+ delegate :middleware, :metal_loader, :to => :config
def require_environment!
environment = paths.config.environment.to_a.first
@@ -125,7 +127,7 @@ module Rails
end
def app
- @app ||= middleware.build(routes)
+ @app ||= config.middleware.build(routes)
end
def call(env)
diff --git a/railties/lib/rails/application/bootstrap.rb b/railties/lib/rails/application/bootstrap.rb
index 022e1a91d8..e62eed8a87 100644
--- a/railties/lib/rails/application/bootstrap.rb
+++ b/railties/lib/rails/application/bootstrap.rb
@@ -10,7 +10,8 @@ module Rails
require environment if environment
end
- initializer :load_all_active_support do
+ initializer :load_active_support do
+ require 'active_support/dependencies'
require "active_support/all" unless config.active_support.bare
end
@@ -18,7 +19,6 @@ module Rails
# Used by Passenger to ensure everything's loaded before forking and
# to avoid autoload race conditions in JRuby.
initializer :preload_frameworks do
- require 'active_support/dependencies'
ActiveSupport::Autoload.eager_autoload! if config.preload_frameworks
end
@@ -66,8 +66,8 @@ module Rails
ActiveSupport::Dependencies.mechanism = config.cache_classes ? :require : :load
end
- initializer :bootstrap_load_path do
- # This is just an initializer used as hook so all load paths are loaded together
+ initializer :bootstrap_hook do |app|
+ ActiveSupport.run_load_hooks(:before_initialize, app)
end
end
end
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 1ad77fdfec..cd77f1adaf 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -33,7 +33,7 @@ module Rails
end
def middleware
- @middleware ||= default_middleware_stack
+ @middleware ||= app_middleware.merge_into(default_middleware_stack)
end
def metal_loader
diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb
index 94507bb387..03bc270c81 100644
--- a/railties/lib/rails/application/finisher.rb
+++ b/railties/lib/rails/application/finisher.rb
@@ -35,10 +35,8 @@ module Rails
app
end
- initializer :after_initialize do
- config.after_initialize_blocks.each do |block|
- block.call(self)
- end
+ initializer :finisher_hook do |app|
+ ActiveSupport.run_load_hooks(:after_initialize, app)
end
# Disable dependency loading during request cycle
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index ab0ead65a9..652bd40ee4 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -45,7 +45,7 @@ module Rails
# app.middleware.use MyEngine::Middleware
# end
# end
- #
+ #
# == Paths
#
# Since Rails 3.0, both your Application and Engines do not have hardcoded paths.
@@ -125,7 +125,7 @@ module Rails
end
end
- delegate :middleware, :paths, :root, :to => :config
+ delegate :paths, :root, :to => :config
def load_tasks
super
@@ -133,7 +133,7 @@ module Rails
end
# Add configured load paths to ruby load paths and remove duplicates.
- initializer :set_load_path, :before => :bootstrap_load_path do
+ initializer :set_load_path, :before => :bootstrap_hook do
config.load_paths.reverse_each do |path|
$LOAD_PATH.unshift(path) if File.directory?(path)
end
@@ -142,7 +142,10 @@ module Rails
# Set the paths from which Rails will automatically load source files,
# and the load_once paths.
- initializer :set_autoload_paths, :before => :bootstrap_load_path do |app|
+ #
+ # This needs to be an initializer, since it needs to run once
+ # per engine and get the engine as a block parameter
+ initializer :set_autoload_paths, :before => :bootstrap_hook do |app|
ActiveSupport::Dependencies.load_paths.unshift(*config.load_paths)
if reloadable?(app)
@@ -200,7 +203,9 @@ module Rails
end
end
- initializer :load_app_classes do |app|
+ # This needs to be an initializer, since it needs to run once
+ # per engine and get the engine as a block parameter
+ initializer :load_app_classes, :before => :finisher_hook do |app|
next if $rails_rake_task
if app.config.cache_classes
diff --git a/railties/lib/rails/railtie/configuration.rb b/railties/lib/rails/railtie/configuration.rb
index 16eccaccc4..f57d82a3d8 100644
--- a/railties/lib/rails/railtie/configuration.rb
+++ b/railties/lib/rails/railtie/configuration.rb
@@ -3,10 +3,50 @@ require 'rails/configuration'
module Rails
class Railtie
class Configuration
+ class MiddlewareStackProxy
+ def initialize
+ @operations = []
+ end
+
+ def insert_before(*args, &block)
+ @operations << [:insert_before, args, block]
+ end
+
+ alias insert insert_before
+
+ def insert_after(*args, &block)
+ @operations << [:insert_after, args, block]
+ end
+
+ def swap(*args, &block)
+ @operations << [:swap, args, block]
+ end
+
+ def use(*args, &block)
+ @operations << [:use, args, block]
+ end
+
+ def merge_into(other)
+ @operations.each do |operation, args, block|
+ other.send(operation, *args, &block)
+ end
+ other
+ end
+ end
+
def initialize
@@options ||= {}
end
+ # This allows you to modify the application's middlewares from Engines.
+ #
+ # All operations you run on the app_middleware will be replayed on the
+ # application once it is defined and the default_middlewares are
+ # created
+ def app_middleware
+ @@app_middleware ||= MiddlewareStackProxy.new
+ end
+
# Holds generators configuration:
#
# config.generators do |g|
@@ -28,12 +68,8 @@ module Rails
end
end
- def after_initialize_blocks
- @@after_initialize_blocks ||= []
- end
-
- def after_initialize(&blk)
- after_initialize_blocks << blk if blk
+ def after_initialize(&block)
+ ActiveSupport.on_load(:after_initialize, :yield => true, &block)
end
def to_prepare_blocks
diff --git a/railties/test/application/initializers/initializers_test.rb b/railties/test/application/initializers/initializers_test.rb
index 2e6a707175..eca42dada6 100644
--- a/railties/test/application/initializers/initializers_test.rb
+++ b/railties/test/application/initializers/initializers_test.rb
@@ -28,19 +28,6 @@ module ApplicationTests
assert_equal "congratulations", $test_after_initialize_block2
end
- test "after_initialize block works correctly when no block is passed" do
- add_to_config <<-RUBY
- config.root = "#{app_path}"
- config.after_initialize { $test_after_initialize_block1 = "success" }
- config.after_initialize # don't pass a block, this is what we're testing!
- config.after_initialize { $test_after_initialize_block2 = "congratulations" }
- RUBY
- require "#{app_path}/config/environment"
-
- assert_equal "success", $test_after_initialize_block1
- assert_equal "congratulations", $test_after_initialize_block2
- end
-
test "after_initialize runs after frameworks have been initialized" do
$activerecord_configurations = nil
add_to_config <<-RUBY