aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarl Lerche <carllerche@mac.com>2009-10-08 12:14:57 -0700
committerCarl Lerche <carllerche@mac.com>2009-10-08 12:31:09 -0700
commite4d7e5090c928e5b64350be9a1fb3aaf6f968e4c (patch)
tree27fe4309341ed992a1f9ca4867f3db6ee46802eb
parent6d6ae0841c94d3c0ce0c91311028ff7396c44a4a (diff)
downloadrails-e4d7e5090c928e5b64350be9a1fb3aaf6f968e4c.tar.gz
rails-e4d7e5090c928e5b64350be9a1fb3aaf6f968e4c.tar.bz2
rails-e4d7e5090c928e5b64350be9a1fb3aaf6f968e4c.zip
Moving more initializers into the application object
-rw-r--r--railties/lib/rails/application.rb93
-rw-r--r--railties/lib/rails/initializable.rb69
-rw-r--r--railties/lib/rails/initializer.rb47
-rw-r--r--railties/test/application/initializable_test.rb26
-rw-r--r--railties/test/application/initializer_test.rb25
-rw-r--r--railties/test/application/plugins_test.rb90
-rw-r--r--railties/test/initializable_test.rb56
-rw-r--r--railties/test/initializer_test.rb95
8 files changed, 292 insertions, 209 deletions
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 783d45aa65..011a9c489d 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -2,34 +2,39 @@ module Rails
class Application
extend Initializable
- def self.inherited(child)
- child.initializers = initializers.dup
- end
+ class << self
+ def config
+ @config ||= Configuration.new
+ end
- def self.config
- @config ||= Configuration.new
- end
+ # TODO: change the plugin loader to use config
+ alias configuration config
- def self.config=(config)
- @config = config
- end
+ def config=(config)
+ @config = config
+ end
- def self.routes
- ActionController::Routing::Routes
- end
+ def plugin_loader
+ @plugin_loader ||= config.plugin_loader.new(self)
+ end
- def self.middleware
- config.middleware
- end
+ def routes
+ ActionController::Routing::Routes
+ end
- def self.call(env)
- @app ||= middleware.build(routes)
- @app.call(env)
- end
+ def middleware
+ config.middleware
+ end
+
+ def call(env)
+ @app ||= middleware.build(routes)
+ @app.call(env)
+ end
- def self.new
- initializers.run
- self
+ def new
+ initializers.run
+ self
+ end
end
initializer :initialize_rails do
@@ -49,5 +54,49 @@ module Rails
abort %{Your config/boot.rb is outdated: Run "rake rails:update".}
end
end
+
+ # Requires all frameworks specified by the Configuration#frameworks
+ # list. By default, all frameworks (Active Record, Active Support,
+ # Action Pack, Action Mailer, and Active Resource) are loaded.
+ initializer :require_frameworks do
+ begin
+ require 'active_support'
+ require 'active_support/core_ext/kernel/reporting'
+ require 'active_support/core_ext/logger'
+
+ # TODO: This is here to make Sam Ruby's tests pass. Needs discussion.
+ require 'active_support/core_ext/numeric/bytes'
+ config.frameworks.each { |framework| require(framework.to_s) }
+ rescue LoadError => e
+ # Re-raise as RuntimeError because Mongrel would swallow LoadError.
+ raise e.to_s
+ end
+ end
+
+ # Set the paths from which Rails will automatically load source files, and
+ # the load_once paths.
+ initializer :set_autoload_paths do
+ require 'active_support/dependencies'
+ ActiveSupport::Dependencies.load_paths = config.load_paths.uniq
+ ActiveSupport::Dependencies.load_once_paths = config.load_once_paths.uniq
+
+ extra = ActiveSupport::Dependencies.load_once_paths - ActiveSupport::Dependencies.load_paths
+ unless extra.empty?
+ abort <<-end_error
+ load_once_paths must be a subset of the load_paths.
+ Extra items in load_once_paths: #{extra * ','}
+ end_error
+ end
+
+ # Freeze the arrays so future modifications will fail rather than do nothing mysteriously
+ config.load_once_paths.freeze
+ end
+
+ # Adds all load paths from plugins to the global set of load paths, so that
+ # code from plugins can be required (explicitly or automatically via ActiveSupport::Dependencies).
+ initializer :add_plugin_load_paths do
+ require 'active_support/dependencies'
+ plugin_loader.add_plugin_load_paths
+ end
end
end
diff --git a/railties/lib/rails/initializable.rb b/railties/lib/rails/initializable.rb
index 61c98d4f99..4bd5088207 100644
--- a/railties/lib/rails/initializable.rb
+++ b/railties/lib/rails/initializable.rb
@@ -2,20 +2,58 @@ module Rails
module Initializable
# A collection of initializers
- class Collection < ActiveSupport::OrderedHash
- # def initialize_copy(other)
- # super
- # each do |key, value|
- # self[key] = value.dup
- # end
- # end
+ class Collection
+ def initialize(context)
+ @context = context
+ @keys = []
+ @values = {}
+ @ran = false
+ end
def run
+ return self if @ran
each do |key, initializer|
- initializer.run
+ @context.class_eval(&initializer.block)
end
+ @ran = true
self
end
+
+ def [](key)
+ keys, values = merge_with_parent
+ values[key.to_sym]
+ end
+
+ def []=(key, value)
+ key = key.to_sym
+ @keys |= [key]
+ @values[key] = value
+ end
+
+ def each
+ keys, values = merge_with_parent
+ keys.each { |k| yield k, values[k] }
+ self
+ end
+
+ protected
+
+ attr_reader :keys, :values
+
+ private
+
+ def merge_with_parent
+ keys, values = [], {}
+
+ if @context.is_a?(Class) && @context.superclass.is_a?(Initializable)
+ parent = @context.superclass.initializers
+ keys, values = parent.keys, parent.values
+ end
+
+ values = values.merge(@values)
+ return keys | @keys, values
+ end
+
end
class Initializer
@@ -24,24 +62,15 @@ module Rails
def initialize(name, options = {}, &block)
@name, @options, @block = name, options, block
end
-
- def run
- return if @already_ran
- @block.call
- @already_ran = true
- end
end
def initializer(name, options = {}, &block)
- initializers[name] = Initializer.new(name, options, &block)
+ @initializers ||= Collection.new(self)
+ @initializers[name] = Initializer.new(name, options, &block)
end
def initializers
- @initializers ||= Collection.new
- end
-
- def initializers=(initializers)
- @initializers = initializers
+ @initializers ||= Collection.new(self)
end
end
diff --git a/railties/lib/rails/initializer.rb b/railties/lib/rails/initializer.rb
index d3e7f934ea..4487cacf7a 100644
--- a/railties/lib/rails/initializer.rb
+++ b/railties/lib/rails/initializer.rb
@@ -1,6 +1,5 @@
require "pathname"
-require 'active_support/ordered_hash'
require 'rails/initializable'
require 'rails/application'
require 'rails/railties_path'
@@ -117,50 +116,6 @@ module Rails
end
end
- # Requires all frameworks specified by the Configuration#frameworks
- # list. By default, all frameworks (Active Record, Active Support,
- # Action Pack, Action Mailer, and Active Resource) are loaded.
- Initializer.default.add :require_frameworks do
- begin
- require 'active_support'
- require 'active_support/core_ext/kernel/reporting'
- require 'active_support/core_ext/logger'
-
- # TODO: This is here to make Sam Ruby's tests pass. Needs discussion.
- require 'active_support/core_ext/numeric/bytes'
- configuration.frameworks.each { |framework| require(framework.to_s) }
- rescue LoadError => e
- # Re-raise as RuntimeError because Mongrel would swallow LoadError.
- raise e.to_s
- end
- end
-
- # Set the paths from which Rails will automatically load source files, and
- # the load_once paths.
- Initializer.default.add :set_autoload_paths do
- require 'active_support/dependencies'
- ActiveSupport::Dependencies.load_paths = configuration.load_paths.uniq
- ActiveSupport::Dependencies.load_once_paths = configuration.load_once_paths.uniq
-
- extra = ActiveSupport::Dependencies.load_once_paths - ActiveSupport::Dependencies.load_paths
- unless extra.empty?
- abort <<-end_error
- load_once_paths must be a subset of the load_paths.
- Extra items in load_once_paths: #{extra * ','}
- end_error
- end
-
- # Freeze the arrays so future modifications will fail rather than do nothing mysteriously
- configuration.load_once_paths.freeze
- end
-
- # Adds all load paths from plugins to the global set of load paths, so that
- # code from plugins can be required (explicitly or automatically via ActiveSupport::Dependencies).
- Initializer.default.add :add_plugin_load_paths do
- require 'active_support/dependencies'
- plugin_loader.add_plugin_load_paths
- end
-
# Create tmp directories
Initializer.default.add :ensure_tmp_directories_exist do
%w(cache pids sessions sockets).each do |dir_to_make|
@@ -373,7 +328,7 @@ module Rails
Initializer.default.add :initialize_metal do
# TODO: Make Rails and metal work without ActionController
- if defined?(ActionController)
+ if configuration.frameworks.include?(:action_controller)
Rails::Rack::Metal.requested_metals = configuration.metals
Rails::Rack::Metal.metal_paths += plugin_loader.engine_metal_paths
diff --git a/railties/test/application/initializable_test.rb b/railties/test/application/initializable_test.rb
deleted file mode 100644
index 38eaec63c0..0000000000
--- a/railties/test/application/initializable_test.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-require "isolation/abstract_unit"
-
-module ApplicationTests
- class InitializerTest < Test::Unit::TestCase
- include ActiveSupport::Testing::Isolation
-
- def setup
- build_app
- boot_rails
- end
-
- test "initializers only ever run once" do
- class MyApp < Rails::Application
- initializer :counter do
- $counter += 1
- end
- end
-
- $counter = 0
- MyApp.initializers[:counter].run
- MyApp.initializers[:counter].run
-
- assert_equal 1, $counter
- end
- end
-end \ No newline at end of file
diff --git a/railties/test/application/initializer_test.rb b/railties/test/application/initializer_test.rb
index 9583e1606c..1b6af718c0 100644
--- a/railties/test/application/initializer_test.rb
+++ b/railties/test/application/initializer_test.rb
@@ -29,5 +29,30 @@ module ApplicationTests
MyApp.new
assert $:.include?("#{app_path}/app/models")
end
+
+ test "adding an unknown framework raises an error" do
+ class MyApp < Rails::Application
+ config.frameworks << :action_foo
+ end
+
+ assert_raises RuntimeError do
+ MyApp.new
+ end
+ end
+
+ test "eager loading loads parent classes before children" do
+ app_file "lib/zoo.rb", <<-ZOO
+ class Zoo ; include ReptileHouse ; end
+ ZOO
+ app_file "lib/zoo/reptile_house.rb", <<-ZOO
+ module Zoo::ReptileHouse ; end
+ ZOO
+
+ Rails::Initializer.run do |config|
+ config.eager_load_paths = "#{app_path}/lib"
+ end
+
+ assert Zoo
+ end
end
end \ No newline at end of file
diff --git a/railties/test/application/plugins_test.rb b/railties/test/application/plugins_test.rb
new file mode 100644
index 0000000000..2a433ea016
--- /dev/null
+++ b/railties/test/application/plugins_test.rb
@@ -0,0 +1,90 @@
+require "isolation/abstract_unit"
+
+module ApplicationTests
+ class PluginTest < Test::Unit::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ def assert_plugins(list_of_names, array_of_plugins, message=nil)
+ assert_equal list_of_names.map { |n| n.to_s }, array_of_plugins.map { |p| p.name }, message
+ end
+
+ def setup
+ build_app
+ boot_rails
+ @failure_tip = "It's likely someone has added a new plugin fixture without updating this list"
+ # Tmp hax to get tests working
+ FileUtils.cp_r "#{File.dirname(__FILE__)}/../fixtures/plugins", "#{app_path}/vendor"
+ end
+
+ test "all plugins are loaded when registered plugin list is untouched" do
+ Rails::Initializer.run { }
+ assert_plugins [
+ :a, :acts_as_chunky_bacon, :engine, :gemlike, :plugin_with_no_lib_dir, :stubby
+ ], Rails.application.config.loaded_plugins, @failure_tip
+ end
+
+ test "all plugins loaded after all" do
+ Rails::Initializer.run do |config|
+ config.plugins = [:stubby, :all, :acts_as_chunky_bacon]
+ end
+ assert_plugins [:stubby, :a, :engine, :gemlike, :plugin_with_no_lib_dir, :acts_as_chunky_bacon], Rails.application.config.loaded_plugins, @failure_tip
+ end
+
+ test "plugin names may be strings" do
+ plugin_names = ['stubby', 'acts_as_chunky_bacon', :a, :plugin_with_no_lib_dir]
+ Rails::Initializer.run do |config|
+ config.plugins = ['stubby', 'acts_as_chunky_bacon', :a, :plugin_with_no_lib_dir]
+ end
+
+ assert_plugins plugin_names, Rails.application.config.loaded_plugins, @failure_tip
+ end
+
+ test "all plugins loaded when all is used" do
+ Rails::Initializer.run do |config|
+ config.plugins = [:stubby, :acts_as_chunky_bacon, :all]
+ end
+
+ assert_plugins [:stubby, :acts_as_chunky_bacon, :a, :engine, :gemlike, :plugin_with_no_lib_dir], Rails.application.config.loaded_plugins, @failure_tip
+ end
+
+ test "all loaded plugins are added to the load paths" do
+ Rails::Initializer.run do |config|
+ config.plugins = [:stubby, :acts_as_chunky_bacon]
+ end
+
+ assert $LOAD_PATH.include?("#{app_path}/vendor/plugins/default/stubby/lib")
+ assert $LOAD_PATH.include?("#{app_path}/vendor/plugins/default/acts/acts_as_chunky_bacon/lib")
+ end
+
+ test "registering a plugin name that does not exist raises a load error" do
+ assert_raise(LoadError) do
+ Rails::Initializer.run do |config|
+ config.plugins = [:stubby, :acts_as_a_non_existant_plugin]
+ end
+ end
+ end
+
+ test "load error messages mention missing plugins and no others" do
+ valid_plugins = [:stubby, :acts_as_chunky_bacon]
+ invalid_plugins = [:non_existant_plugin1, :non_existant_plugin2]
+
+ begin
+ Rails::Initializer.run do |config|
+ config.plugins = [:stubby, :acts_as_chunky_bacon, :non_existant_plugin1, :non_existant_plugin2]
+ end
+ flunk "Expected a LoadError but did not get one"
+ rescue LoadError => e
+ assert_plugins valid_plugins, Rails.application.config.loaded_plugins, @failure_tip
+
+ invalid_plugins.each do |plugin|
+ assert_match(/#{plugin.to_s}/, e.message, "LoadError message should mention plugin '#{plugin}'")
+ end
+
+ valid_plugins.each do |plugin|
+ assert_no_match(/#{plugin.to_s}/, e.message, "LoadError message should not mention '#{plugin}'")
+ end
+ end
+ end
+
+ end
+end \ No newline at end of file
diff --git a/railties/test/initializable_test.rb b/railties/test/initializable_test.rb
new file mode 100644
index 0000000000..4d8b429a4f
--- /dev/null
+++ b/railties/test/initializable_test.rb
@@ -0,0 +1,56 @@
+require 'abstract_unit'
+require 'rails/initializable'
+
+module InitializableTests
+
+ class Foo
+ extend Rails::Initializable
+
+ class << self
+ attr_accessor :foo, :bar
+ end
+
+ initializer :omg do
+ @foo ||= 0
+ @foo += 1
+ end
+ end
+
+ class Bar < Foo
+ initializer :bar do
+ @bar ||= 0
+ @bar += 1
+ end
+ end
+
+ class Basic < ActiveSupport::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ test "initializers run" do
+ Foo.initializers.run
+ assert_equal 1, Foo.foo
+ end
+
+ test "initializers are inherited" do
+ Bar.initializers.run
+ assert_equal [1, 1], [Bar.foo, Bar.bar]
+ end
+
+ test "initializers only get run once" do
+ Foo.initializers.run
+ Foo.initializers.run
+ assert_equal 1, Foo.foo
+ end
+
+ test "running initializers on children does not effect the parent" do
+ Bar.initializers.run
+ assert_nil Foo.foo
+ assert_nil Foo.bar
+ end
+
+ test "inherited initializers are the same objects" do
+ assert Foo.initializers[:foo].eql?(Bar.initializers[:foo])
+ end
+
+ end
+end \ No newline at end of file
diff --git a/railties/test/initializer_test.rb b/railties/test/initializer_test.rb
index 92383a74fd..616374b183 100644
--- a/railties/test/initializer_test.rb
+++ b/railties/test/initializer_test.rb
@@ -44,25 +44,6 @@ class Initializer_load_environment_Test < Test::Unit::TestCase
end
end
-class Initializer_eager_loading_Test < Test::Unit::TestCase
- def setup
- @config = ConfigurationMock.new("")
- @config.cache_classes = true
- @config.load_paths = [File.expand_path(File.dirname(__FILE__) + "/fixtures/eager")]
- @config.eager_load_paths = [File.expand_path(File.dirname(__FILE__) + "/fixtures/eager")]
- @initializer = Rails::Initializer.default
- @initializer.config = @config
- @initializer.run(:set_load_path)
- @initializer.run(:set_autoload_paths)
- end
-
- def test_eager_loading_loads_parent_classes_before_children
- assert_nothing_raised do
- @initializer.run(:load_application_classes)
- end
- end
-end
-
class Initializer_after_initialize_with_blocks_environment_Test < Test::Unit::TestCase
def setup
config = ConfigurationMock.new("")
@@ -154,16 +135,6 @@ class ConfigurationFrameworkPathsTests < Test::Unit::TestCase
end
end
- def test_unknown_framework_raises_error
- @config.frameworks << :action_foo
-
- Class.any_instance.expects(:require).raises(LoadError)
-
- assert_raise RuntimeError do
- @initializer.run(:require_frameworks)
- end
- end
-
def test_action_mailer_load_paths_set_only_if_action_mailer_in_use
@config.frameworks = [:action_controller]
@initializer.config = @config
@@ -216,72 +187,6 @@ class InitializerPluginLoadingTests < Test::Unit::TestCase
assert_plugins plugin_names, @configuration.loaded_plugins
end
- def test_all_plugins_are_loaded_when_registered_plugin_list_is_untouched
- failure_tip = "It's likely someone has added a new plugin fixture without updating this list"
- load_plugins!
- assert_plugins [:a, :acts_as_chunky_bacon, :engine, :gemlike, :plugin_with_no_lib_dir, :stubby], @configuration.loaded_plugins, failure_tip
- end
-
- def test_all_plugins_loaded_when_all_is_used
- plugin_names = [:stubby, :acts_as_chunky_bacon, :all]
- only_load_the_following_plugins! plugin_names
- load_plugins!
- failure_tip = "It's likely someone has added a new plugin fixture without updating this list"
- assert_plugins [:stubby, :acts_as_chunky_bacon, :a, :engine, :gemlike, :plugin_with_no_lib_dir], @configuration.loaded_plugins, failure_tip
- end
-
- def test_all_plugins_loaded_after_all
- plugin_names = [:stubby, :all, :acts_as_chunky_bacon]
- only_load_the_following_plugins! plugin_names
- load_plugins!
- failure_tip = "It's likely someone has added a new plugin fixture without updating this list"
- assert_plugins [:stubby, :a, :engine, :gemlike, :plugin_with_no_lib_dir, :acts_as_chunky_bacon], @configuration.loaded_plugins, failure_tip
- end
-
- def test_plugin_names_may_be_strings
- plugin_names = ['stubby', 'acts_as_chunky_bacon', :a, :plugin_with_no_lib_dir]
- only_load_the_following_plugins! plugin_names
- load_plugins!
- failure_tip = "It's likely someone has added a new plugin fixture without updating this list"
- assert_plugins plugin_names, @configuration.loaded_plugins, failure_tip
- end
-
- def test_registering_a_plugin_name_that_does_not_exist_raises_a_load_error
- only_load_the_following_plugins! [:stubby, :acts_as_a_non_existant_plugin]
- assert_raise(LoadError) do
- load_plugins!
- end
- end
-
- def test_load_error_messages_mention_missing_plugins_and_no_others
- valid_plugin_names = [:stubby, :acts_as_chunky_bacon]
- invalid_plugin_names = [:non_existant_plugin1, :non_existant_plugin2]
- only_load_the_following_plugins!( valid_plugin_names + invalid_plugin_names )
- begin
- load_plugins!
- flunk "Expected a LoadError but did not get one"
- rescue LoadError => e
- failure_tip = "It's likely someone renamed or deleted plugin fixtures without updating this test"
- assert_plugins valid_plugin_names, @configuration.loaded_plugins, failure_tip
- invalid_plugin_names.each do |plugin|
- assert_match(/#{plugin.to_s}/, e.message, "LoadError message should mention plugin '#{plugin}'")
- end
- valid_plugin_names.each do |plugin|
- assert_no_match(/#{plugin.to_s}/, e.message, "LoadError message should not mention '#{plugin}'")
- end
-
- end
- end
-
- def test_should_ensure_all_loaded_plugins_load_paths_are_added_to_the_load_path
- only_load_the_following_plugins! [:stubby, :acts_as_chunky_bacon]
-
- @initializer.run(:add_plugin_load_paths)
-
- assert $LOAD_PATH.include?(File.join(plugin_fixture_path('default/stubby'), 'lib'))
- assert $LOAD_PATH.include?(File.join(plugin_fixture_path('default/acts/acts_as_chunky_bacon'), 'lib'))
- end
-
private
def load_plugins!