From 6d6ae0841c94d3c0ce0c91311028ff7396c44a4a Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Wed, 7 Oct 2009 15:21:19 -0700 Subject: Start moving the initializers into the application object --- railties/lib/rails/application.rb | 38 +++++++++--- .../generators/rails/app/templates/config/boot.rb | 13 ++-- railties/lib/rails/initializable.rb | 70 ++++++++++++++++++++++ railties/lib/rails/initializer.rb | 42 ++----------- railties/test/application/initializable_test.rb | 26 ++++++++ railties/test/application/initializer_test.rb | 33 ++++++++++ railties/test/application/load_test.rb | 4 +- railties/test/initializer/initialize_i18n_test.rb | 51 ++++++++++++++++ railties/test/initializer_test.rb | 18 ------ railties/test/isolation/abstract_unit.rb | 3 +- 10 files changed, 225 insertions(+), 73 deletions(-) create mode 100644 railties/lib/rails/initializable.rb create mode 100644 railties/test/application/initializable_test.rb create mode 100644 railties/test/application/initializer_test.rb create mode 100644 railties/test/initializer/initialize_i18n_test.rb diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index 6139e20e95..783d45aa65 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -1,5 +1,10 @@ module Rails class Application + extend Initializable + + def self.inherited(child) + child.initializers = initializers.dup + end def self.config @config ||= Configuration.new @@ -9,21 +14,40 @@ module Rails @config = config end - def config - self.class.config - end - - def routes + def self.routes ActionController::Routing::Routes end - def middleware + def self.middleware config.middleware end - def call(env) + def self.call(env) @app ||= middleware.build(routes) @app.call(env) end + + def self.new + initializers.run + self + end + + initializer :initialize_rails do + Rails.initializers.run + end + + # Set the $LOAD_PATH based on the value of + # Configuration#load_paths. Duplicates are removed. + initializer :set_load_path do + config.paths.add_to_load_path + $LOAD_PATH.uniq! + end + + # Bail if boot.rb is outdated + initializer :freak_out_if_boot_rb_is_outdated do + unless defined?(Rails::BOOTSTRAP_VERSION) + abort %{Your config/boot.rb is outdated: Run "rake rails:update".} + end + end end end diff --git a/railties/lib/rails/generators/rails/app/templates/config/boot.rb b/railties/lib/rails/generators/rails/app/templates/config/boot.rb index 52086fbc7d..6e0e2279cd 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/boot.rb +++ b/railties/lib/rails/generators/rails/app/templates/config/boot.rb @@ -40,20 +40,20 @@ module Rails class Boot def run - load_initializer set_load_paths + load_initializer end def set_load_paths %w( - railties - railties/lib - activesupport/lib + actionmailer/lib actionpack/lib + activemodel/lib activerecord/lib - actionmailer/lib activeresource/lib - actionwebservice/lib + activesupport/lib + railties/lib + railties ).reverse_each do |path| path = "#{framework_root_path}/#{path}" $LOAD_PATH.unshift(path) if File.directory?(path) @@ -68,7 +68,6 @@ module Rails class VendorBoot < Boot def load_initializer - $:.unshift("#{framework_root_path}/railties/lib") require "rails" install_gem_spec_stubs Rails::GemDependency.add_frozen_gem_path diff --git a/railties/lib/rails/initializable.rb b/railties/lib/rails/initializable.rb new file mode 100644 index 0000000000..61c98d4f99 --- /dev/null +++ b/railties/lib/rails/initializable.rb @@ -0,0 +1,70 @@ +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 + + def run + each do |key, initializer| + initializer.run + end + self + end + end + + class Initializer + attr_reader :name, :options, :block + + 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) + end + + def initializers + @initializers ||= Collection.new + end + + def initializers=(initializers) + @initializers = initializers + end + + end + + extend Initializable + + # Check for valid Ruby version (1.8.2 or 1.8.4 or higher). This is done in an + # external file, so we can use it from the `rails` program as well without duplication. + initializer :check_ruby_version do + require 'rails/ruby_version_check' + end + + # For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the + # multibyte safe operations. Plugin authors supporting other encodings + # should override this behaviour and set the relevant +default_charset+ + # on ActionController::Base. + # + # For Ruby 1.9, UTF-8 is the default internal and external encoding. + initializer :initialize_encoding do + if RUBY_VERSION < '1.9' + $KCODE='u' + else + Encoding.default_external = Encoding::UTF_8 + end + end +end \ No newline at end of file diff --git a/railties/lib/rails/initializer.rb b/railties/lib/rails/initializer.rb index c2d6e1609f..d3e7f934ea 100644 --- a/railties/lib/rails/initializer.rb +++ b/railties/lib/rails/initializer.rb @@ -1,5 +1,7 @@ require "pathname" +require 'active_support/ordered_hash' +require 'rails/initializable' require 'rails/application' require 'rails/railties_path' require 'rails/version' @@ -12,10 +14,6 @@ require 'rails/configuration' RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV) module Rails - # Sanity check to make sure this file is only loaded once - # TODO: Get to the point where this can be removed. - raise "It looks like initializer.rb was required twice" if defined?(Initializer) - class Initializer class Error < StandardError ; end @@ -110,6 +108,8 @@ module Rails default.run(initializer) else Rails.application = Class.new(Application) + # Trigger the initializer + Rails.application.new yield Rails.application.config if block_given? default.config = Rails.application.config default.run @@ -117,26 +117,6 @@ module Rails end end - # Check for valid Ruby version (1.8.2 or 1.8.4 or higher). This is done in an - # external file, so we can use it from the `rails` program as well without duplication. - Initializer.default.add :check_ruby_version do - require 'rails/ruby_version_check' - end - - # Bail if boot.rb is outdated - Initializer.default.add :freak_out_if_boot_rb_is_outdated do - unless defined?(Rails::BOOTSTRAP_VERSION) - abort %{Your config/boot.rb is outdated: Run "rake rails:update".} - end - end - - # Set the $LOAD_PATH based on the value of - # Configuration#load_paths. Duplicates are removed. - Initializer.default.add :set_load_path do - configuration.paths.add_to_load_path - $LOAD_PATH.uniq! - 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. @@ -230,20 +210,6 @@ module Rails end end - # For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the - # multibyte safe operations. Plugin authors supporting other encodings - # should override this behaviour and set the relevant +default_charset+ - # on ActionController::Base. - # - # For Ruby 1.9, UTF-8 is the default internal and external encoding. - Initializer.default.add :initialize_encoding do - if RUBY_VERSION < '1.9' - $KCODE='u' - else - Encoding.default_external = Encoding::UTF_8 - end - end - # This initialization routine does nothing unless :active_record # is one of the frameworks to load (Configuration#frameworks). If it is, # this sets the database configuration from Configuration#database_configuration diff --git a/railties/test/application/initializable_test.rb b/railties/test/application/initializable_test.rb new file mode 100644 index 0000000000..38eaec63c0 --- /dev/null +++ b/railties/test/application/initializable_test.rb @@ -0,0 +1,26 @@ +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 new file mode 100644 index 0000000000..9583e1606c --- /dev/null +++ b/railties/test/application/initializer_test.rb @@ -0,0 +1,33 @@ +require "isolation/abstract_unit" + +module ApplicationTests + class InitializerTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + end + + test "initializing an application initializes rails" do + class MyApp < Rails::Application ; end + + if RUBY_VERSION < '1.9' + $KCODE = '' + MyApp.new + assert_equal 'UTF8', $KCODE + else + Encoding.default_external = Encoding::US_ASCII + MyApp.new + assert_equal Encoding::UTF_8, Encoding.default_external + end + end + + test "initializing an application adds the application paths to the load path" do + class MyApp < Rails::Application ; end + + MyApp.new + assert $:.include?("#{app_path}/app/models") + end + end +end \ No newline at end of file diff --git a/railties/test/application/load_test.rb b/railties/test/application/load_test.rb index 305cd7f273..5c3d35fb16 100644 --- a/railties/test/application/load_test.rb +++ b/railties/test/application/load_test.rb @@ -40,14 +40,14 @@ module ApplicationTests test "Rails.application is available after config.ru has been racked up" do rackup - assert Rails.application.new.is_a?(Rails::Application) + assert Rails.application.new < Rails::Application end # Passenger still uses AC::Dispatcher, so we need to # keep it working for now test "deprecated ActionController::Dispatcher still works" do rackup - assert ActionController::Dispatcher.new.is_a?(Rails::Application) + assert ActionController::Dispatcher.new < Rails::Application end test "the config object is available on the application object" do diff --git a/railties/test/initializer/initialize_i18n_test.rb b/railties/test/initializer/initialize_i18n_test.rb new file mode 100644 index 0000000000..e909688817 --- /dev/null +++ b/railties/test/initializer/initialize_i18n_test.rb @@ -0,0 +1,51 @@ +require "isolation/abstract_unit" + +module InitializerTests + class InitializeI18nTest < Test::Unit::TestCase + include ActiveSupport::Testing::Isolation + + def setup + build_app + boot_rails + end + + # test_config_defaults_and_settings_should_be_added_to_i18n_defaults + test "i18n config defaults and settings should be added to i18n defaults" do + Rails::Initializer.run do |c| + c.i18n.load_path << "my/other/locale.yml" + end + + #{RAILS_FRAMEWORK_ROOT}/railties/test/fixtures/plugins/engines/engine/config/locales/en.yml + assert_equal %W( + #{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/locale/en.yml + #{RAILS_FRAMEWORK_ROOT}/activemodel/lib/active_model/locale/en.yml + #{RAILS_FRAMEWORK_ROOT}/activerecord/lib/active_record/locale/en.yml + #{RAILS_FRAMEWORK_ROOT}/actionpack/lib/action_view/locale/en.yml + #{RAILS_FRAMEWORK_ROOT}/railties/tmp/app/config/locales/en.yml + my/other/locale.yml + ), I18n.load_path + end + + test "i18n finds locale files in engines" do + app_file "vendor/plugins/engine/init.rb", "" + app_file "vendor/plugins/engine/app/models/hellos.rb", "class Hello ; end" + app_file "vendor/plugins/engine/lib/omg.rb", "puts 'omg'" + app_file "vendor/plugins/engine/config/locales/en.yml", "hello:" + + Rails::Initializer.run do |c| + c.i18n.load_path << "my/other/locale.yml" + end + + #{RAILS_FRAMEWORK_ROOT}/railties/test/fixtures/plugins/engines/engine/config/locales/en.yml + assert_equal %W( + #{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/locale/en.yml + #{RAILS_FRAMEWORK_ROOT}/activemodel/lib/active_model/locale/en.yml + #{RAILS_FRAMEWORK_ROOT}/activerecord/lib/active_record/locale/en.yml + #{RAILS_FRAMEWORK_ROOT}/actionpack/lib/action_view/locale/en.yml + #{app_path}/config/locales/en.yml + my/other/locale.yml + #{app_path}/vendor/plugins/engine/config/locales/en.yml + ), I18n.load_path + end + end +end \ No newline at end of file diff --git a/railties/test/initializer_test.rb b/railties/test/initializer_test.rb index b67db9c835..92383a74fd 100644 --- a/railties/test/initializer_test.rb +++ b/railties/test/initializer_test.rb @@ -393,24 +393,6 @@ class InitializerSetupI18nTests < Test::Unit::TestCase assert_equal [ "my/test/locale.yml", "my/other/locale.yml" ], config.i18n.load_path end - def test_config_defaults_and_settings_should_be_added_to_i18n_defaults - File.stubs(:exist?).returns(true) - Dir.stubs(:[]).returns([ "my/test/locale.yml" ]) - - config = Rails::Configuration.new - config.i18n.load_path << "my/other/locale.yml" - - Rails::Initializer.run(:initialize_i18n, config) - assert_equal [ - File.expand_path(File.dirname(__FILE__) + "/../../activesupport/lib/active_support/locale/en.yml"), - File.expand_path(File.dirname(__FILE__) + "/../../actionpack/lib/action_view/locale/en.yml"), - File.expand_path(File.dirname(__FILE__) + "/../../activemodel/lib/active_model/locale/en.yml"), - File.expand_path(File.dirname(__FILE__) + "/../../activerecord/lib/active_record/locale/en.yml"), - File.expand_path(File.dirname(__FILE__) + "/../../railties/test/fixtures/plugins/engines/engine/config/locales/en.yml"), - "my/test/locale.yml", - "my/other/locale.yml" ], I18n.load_path.collect { |path| path =~ /\.\./ ? File.expand_path(path) : path } - end - def test_setting_another_default_locale config = Rails::Configuration.new config.i18n.default_locale = :de diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index a55ee6c01d..c452adaa52 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -91,7 +91,8 @@ module TestHelpers end def app_file(path, contents) - File.open(app_path(path), 'w') do |f| + FileUtils.mkdir_p File.dirname("#{app_path}/#{path}") + File.open("#{app_path}/#{path}", 'w') do |f| f.puts contents end end -- cgit v1.2.3