aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Rosania <paul.rosania@gmail.com>2010-01-27 01:08:50 -0500
committerJeremy Kemper <jeremy@bitsweat.net>2010-01-29 19:25:58 -0800
commit766e857bea9bd29f27be1ccd888eec066f2e3f04 (patch)
tree8fb8934ba767997fd944c70379d01fcdbb6d6342
parenta06c47a52b90a5d812e64309488ad5926dc583ca (diff)
downloadrails-766e857bea9bd29f27be1ccd888eec066f2e3f04.tar.gz
rails-766e857bea9bd29f27be1ccd888eec066f2e3f04.tar.bz2
rails-766e857bea9bd29f27be1ccd888eec066f2e3f04.zip
tsort-based dependency resolution for initializers
Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
-rw-r--r--activerecord/lib/active_record/railtie.rb2
-rw-r--r--railties/lib/rails/initializable.rb29
-rw-r--r--railties/lib/rails/plugin.rb2
-rw-r--r--railties/test/initializable_test.rb43
-rw-r--r--railties/test/railties/plugin_test.rb2
5 files changed, 56 insertions, 22 deletions
diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb
index dc80ac4b30..30da494d57 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -50,7 +50,7 @@ module ActiveRecord
end
# Setup database middleware after initializers have run
- initializer "active_record.initialize_database_middleware" do |app|
+ initializer "active_record.initialize_database_middleware", :after => "action_controller.set_configs" do |app|
middleware = app.config.middleware
if middleware.include?("ActiveRecord::SessionStore")
middleware.insert_before "ActiveRecord::SessionStore", ActiveRecord::ConnectionAdapters::ConnectionManagement
diff --git a/railties/lib/rails/initializable.rb b/railties/lib/rails/initializable.rb
index d91f67823f..9a82e051e7 100644
--- a/railties/lib/rails/initializable.rb
+++ b/railties/lib/rails/initializable.rb
@@ -1,3 +1,5 @@
+require 'tsort'
+
module Rails
module Initializable
def self.included(base)
@@ -30,29 +32,21 @@ module Rails
end
class Collection < Array
+ include TSort
+
+ alias :tsort_each_node :each
+ def tsort_each_child(initializer, &block)
+ select { |i| i.before == initializer.name || i.name == initializer.after }.each(&block)
+ end
+
def initialize(initializers = [])
- super()
- initializers.each do |initializer|
- if initializer.before
- index = index_for(initializer.before)
- elsif initializer.after
- index = index_for(initializer.after)
- index += 1 if index
- else
- index = length
- end
- insert(index || -1, initializer)
- end
+ super(initializers)
+ replace(tsort)
end
def +(other)
Collection.new(to_a + other.to_a)
end
-
- def index_for(name)
- initializer = find { |i| i.name == name }
- initializer && index(initializer)
- end
end
def run_initializers(*args)
@@ -87,6 +81,7 @@ module Rails
def initializer(name, opts = {}, &blk)
raise ArgumentError, "A block must be passed when defining an initializer" unless blk
+ opts[:after] ||= initializers.last.name unless initializers.empty? || initializers.find { |i| i.name == opts[:before] }
initializers << Initializer.new(name, nil, opts, &blk)
end
diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb
index 881c97f02d..64d03e7599 100644
--- a/railties/lib/rails/plugin.rb
+++ b/railties/lib/rails/plugin.rb
@@ -43,7 +43,7 @@ module Rails
@config ||= Engine::Configuration.new
end
- initializer :load_init_rb do |app|
+ initializer :load_init_rb, :before => :load_application_initializers do |app|
file = Dir["#{root}/{rails/init,init}.rb"].first
config = app.config
eval(File.read(file), binding, file) if file && File.file?(file)
diff --git a/railties/test/initializable_test.rb b/railties/test/initializable_test.rb
index 0c7378cb64..6a7e4dcc25 100644
--- a/railties/test/initializable_test.rb
+++ b/railties/test/initializable_test.rb
@@ -50,7 +50,7 @@ module InitializableTests
$arr << 3
end
- initializer :four, :after => :one do
+ initializer :four, :after => :one, :before => :two do
$arr << 4
end
end
@@ -97,7 +97,7 @@ module InitializableTests
$arr << 3
end
- initializer :terminate, :after => :first do
+ initializer :terminate, :after => :first, :before => :startup do
$arr << two
end
@@ -121,6 +121,39 @@ module InitializableTests
end
end
+ module Interdependent
+ class PluginA
+ include Rails::Initializable
+
+ initializer "plugin_a.startup" do
+ $arr << 1
+ end
+
+ initializer "plugin_a.terminate" do
+ $arr << 4
+ end
+ end
+
+ class PluginB
+ include Rails::Initializable
+
+ initializer "plugin_b.startup", :after => "plugin_a.startup" do
+ $arr << 2
+ end
+
+ initializer "plugin_b.terminate", :before => "plugin_a.terminate" do
+ $arr << 3
+ end
+ end
+
+ class Application
+ include Rails::Initializable
+ def self.initializers
+ PluginB.initializers + PluginA.initializers
+ end
+ end
+ end
+
class Basic < ActiveSupport::TestCase
include ActiveSupport::Testing::Isolation
@@ -174,6 +207,12 @@ module InitializableTests
Child.run_initializers
assert_equal [5, 3, 1, 4, 2], $arr
end
+
+ test "handles dependencies introduced before all initializers are loaded" do
+ $arr = []
+ Interdependent::Application.run_initializers
+ assert_equal [1, 2, 3, 4], $arr
+ end
end
class InstanceTest < ActiveSupport::TestCase
diff --git a/railties/test/railties/plugin_test.rb b/railties/test/railties/plugin_test.rb
index 997b692e49..09b859dcdd 100644
--- a/railties/test/railties/plugin_test.rb
+++ b/railties/test/railties/plugin_test.rb
@@ -47,7 +47,7 @@ module RailtiesTest
assert_equal :debug, LEVEL
end
- test "plugin_init_is_ran_before_application_ones" do
+ test "plugin_init_is_run_before_application_ones" do
plugin "foo", "$foo = true" do |plugin|
plugin.write "lib/foo.rb", "module Foo; end"
end