From 54efce617f79daa11c00b9464185060a501280cf Mon Sep 17 00:00:00 2001 From: Daniel Libanori Date: Wed, 12 Aug 2009 16:26:09 -0300 Subject: [PATCH] Added reset_subclasses option to configuration. To avoid STI subclasses problems, you can configure you envimenroment to don't reset subclasses loaded on each request, so, one time you load any AR::Base inherited it will stay in its parent subclasses list. config.reset_subclasses = false --- .../lib/action_controller/dispatch/dispatcher.rb | 4 ++-- actionpack/test/controller/dispatcher_test.rb | 19 +++++++++++++------ railties/lib/initializer.rb | 2 +- railties/lib/initializer_old.rb | 11 ++++++++++- railties/lib/rails/configuration.rb | 3 ++- railties/test/initializer_test.rb | 1 + 6 files changed, 29 insertions(+), 11 deletions(-) diff --git a/actionpack/lib/action_controller/dispatch/dispatcher.rb b/actionpack/lib/action_controller/dispatch/dispatcher.rb index 9ad1cad..a235e27 100644 --- a/actionpack/lib/action_controller/dispatch/dispatcher.rb +++ b/actionpack/lib/action_controller/dispatch/dispatcher.rb @@ -17,7 +17,7 @@ module ActionController end class << self - def define_dispatcher_callbacks(cache_classes) + def define_dispatcher_callbacks(cache_classes, reset_subclasses) unless cache_classes # Run prepare callbacks before every request in development mode self.prepare_each_request = true @@ -29,7 +29,7 @@ module ActionController ActionDispatch::Callbacks.after_dispatch do # Cleanup the application before processing the current request. - ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord) + ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord) && reset_subclasses ActiveSupport::Dependencies.clear ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord) end diff --git a/actionpack/test/controller/dispatcher_test.rb b/actionpack/test/controller/dispatcher_test.rb index 9fae1fc..d7b8a1c 100644 --- a/actionpack/test/controller/dispatcher_test.rb +++ b/actionpack/test/controller/dispatcher_test.rb @@ -1,4 +1,5 @@ require 'abstract_unit' +require 'active_record_unit' class DispatcherTest < Test::Unit::TestCase Dispatcher = ActionController::Dispatcher @@ -77,10 +78,20 @@ class DispatcherTest < Test::Unit::TestCase assert_equal nil, b end + def test_reset_subclasses + ActiveRecord::Base.expects(:reset_subclasses).never + dispatch(false, false) + end + + def test_dont_reset_subclasses + ActiveRecord::Base.expects(:reset_subclasses).once + dispatch(false) + end + private - def dispatch(cache_classes = true) + def dispatch(cache_classes = true, reset_subclasses = true) ActionController::Dispatcher.prepare_each_request = false - Dispatcher.define_dispatcher_callbacks(cache_classes) + Dispatcher.define_dispatcher_callbacks(cache_classes, reset_subclasses) Dispatcher.middleware = ActionDispatch::MiddlewareStack.new do |middleware| middlewares = File.expand_path(File.join(File.dirname(__FILE__), "../../lib/action_controller/dispatch/middlewares.rb")) middleware.instance_eval(File.read(middlewares)) @@ -89,8 +100,4 @@ class DispatcherTest < Test::Unit::TestCase @dispatcher ||= Dispatcher.new @dispatcher.call({'rack.input' => StringIO.new(''), 'action_dispatch.show_exceptions' => false}) end - - def assert_subclasses(howmany, klass, message = klass.subclasses.inspect) - assert_equal howmany, klass.subclasses.size, message - end end diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 336bff9..3c0a005 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -524,7 +524,7 @@ Run `rake gems:install` to install the missing gems. Initializer.default.add :prepare_dispatcher do next unless configuration.frameworks.include?(:action_controller) require 'dispatcher' unless defined?(::Dispatcher) - Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) + Dispatcher.define_dispatcher_callbacks(configuration.cache_classes, configuration.reset_subclasses) end # Routing must be initialized after plugins to allow the former to extend the routes diff --git a/railties/lib/initializer_old.rb b/railties/lib/initializer_old.rb index cee5c7b..ec9e9cb 100644 --- a/railties/lib/initializer_old.rb +++ b/railties/lib/initializer_old.rb @@ -635,7 +635,7 @@ Run `rake gems:install` to install the missing gems. def prepare_dispatcher return unless configuration.frameworks.include?(:action_controller) require 'dispatcher' unless defined?(::Dispatcher) - Dispatcher.define_dispatcher_callbacks(configuration.cache_classes) + Dispatcher.define_dispatcher_callbacks(configuration.cache_classes, configuration.reset_subclasses) end def disable_dependency_loading @@ -683,6 +683,10 @@ Run `rake gems:install` to install the missing gems. # application classes to be reloaded on each request) attr_accessor :cache_classes + # Whether or not active record subclasses should be cached (set to true + # if you want to reset all subclasses from each ActiveRecord::Base subclass) + attr_accessor :reset_subclasses + # The list of paths that should be searched for controllers. (Defaults # to app/controllers.) attr_accessor :controller_paths @@ -852,6 +856,7 @@ Run `rake gems:install` to install the missing gems. self.controller_paths = default_controller_paths self.preload_frameworks = default_preload_frameworks self.cache_classes = default_cache_classes + self.reset_subclasses = default_reset_subclasses self.dependency_loading = default_dependency_loading self.whiny_nils = default_whiny_nils self.plugins = default_plugins @@ -1050,6 +1055,10 @@ Run `rake gems:install` to install the missing gems. true end + def default_reset_subclasses + true + end + def default_whiny_nils false end diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 5cc4f80..b4014d8 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -1,6 +1,6 @@ module Rails class Configuration - attr_accessor :cache_classes, :load_paths, :eager_load_paths, :framework_paths, + attr_accessor :cache_classes, :reset_subclasses, :load_paths, :eager_load_paths, :framework_paths, :load_once_paths, :gems_dependencies_loaded, :after_initialize_blocks, :frameworks, :framework_root_path, :root_path, :plugin_paths, :plugins, :plugin_loader, :plugin_locators, :gems, :loaded_plugins, :reload_plugins, @@ -20,6 +20,7 @@ module Rails @after_initialize_blocks = [] @loaded_plugins = [] @dependency_loading = true + @reset_subclasses = true @eager_load_paths = default_eager_load_paths @load_paths = default_load_paths @plugin_paths = default_plugin_paths diff --git a/railties/test/initializer_test.rb b/railties/test/initializer_test.rb index 1fecd62..3cea2ae 100644 --- a/railties/test/initializer_test.rb +++ b/railties/test/initializer_test.rb @@ -48,6 +48,7 @@ class Initializer_eager_loading_Test < Test::Unit::TestCase def setup @config = ConfigurationMock.new("") @config.cache_classes = true + @config.reset_subclasses = 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 -- 1.6.0.4 From ea87de099d202dd663521875b4b5e131c2b91315 Mon Sep 17 00:00:00 2001 From: Daniel Libanori Date: Wed, 12 Aug 2009 17:06:17 -0300 Subject: [PATCH] Added load_application_classes option to configuration. Now eager load application uses load_application_classes instead cache_classes option. Its default value is true. config.load_application_classes = true --- .../templates/config/environments/development.rb | 4 +++- railties/lib/initializer.rb | 2 +- railties/lib/initializer_old.rb | 11 ++++++++++- railties/lib/rails/configuration.rb | 5 ++++- railties/test/initializer_test.rb | 1 + 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/railties/lib/generators/rails/app/templates/config/environments/development.rb b/railties/lib/generators/rails/app/templates/config/environments/development.rb index 85c9a60..ad65f40 100644 --- a/railties/lib/generators/rails/app/templates/config/environments/development.rb +++ b/railties/lib/generators/rails/app/templates/config/environments/development.rb @@ -4,6 +4,8 @@ # every request. This slows down response time but is perfect for development # since you don't have to restart the webserver when you make code changes. config.cache_classes = false +config.reset_subclasses = false +config.load_application_classes = false # Log error messages when you accidentally call methods on nil. config.whiny_nils = true @@ -14,4 +16,4 @@ config.action_view.debug_rjs = true config.action_controller.perform_caching = false # Don't care if the mailer can't send -config.action_mailer.raise_delivery_errors = false \ No newline at end of file +config.action_mailer.raise_delivery_errors = false diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb index 3c0a005..2ba02dd 100644 --- a/railties/lib/initializer.rb +++ b/railties/lib/initializer.rb @@ -551,7 +551,7 @@ Run `rake gems:install` to install the missing gems. Initializer.default.add :load_application_classes do next if $rails_rake_task - if configuration.cache_classes + if configuration.load_application_classes configuration.eager_load_paths.each do |load_path| matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/ Dir.glob("#{load_path}/**/*.rb").sort.each do |file| diff --git a/railties/lib/initializer_old.rb b/railties/lib/initializer_old.rb index ec9e9cb..c6a47cb 100644 --- a/railties/lib/initializer_old.rb +++ b/railties/lib/initializer_old.rb @@ -411,7 +411,7 @@ Run `rake gems:install` to install the missing gems. # Eager load application classes def load_application_classes return if $rails_rake_task - if configuration.cache_classes + if configuration.load_application_classes configuration.eager_load_paths.each do |load_path| matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/ Dir.glob("#{load_path}/**/*.rb").sort.each do |file| @@ -687,6 +687,9 @@ Run `rake gems:install` to install the missing gems. # if you want to reset all subclasses from each ActiveRecord::Base subclass) attr_accessor :reset_subclasses + # Eager load application classes + attr_accessor :load_application_classes + # The list of paths that should be searched for controllers. (Defaults # to app/controllers.) attr_accessor :controller_paths @@ -857,6 +860,7 @@ Run `rake gems:install` to install the missing gems. self.preload_frameworks = default_preload_frameworks self.cache_classes = default_cache_classes self.reset_subclasses = default_reset_subclasses + self.load_application_classes = default_load_application_classes self.dependency_loading = default_dependency_loading self.whiny_nils = default_whiny_nils self.plugins = default_plugins @@ -901,6 +905,7 @@ Run `rake gems:install` to install the missing gems. def threadsafe! self.preload_frameworks = true self.cache_classes = true + self.load_application_classes = true self.dependency_loading = false self.action_controller.allow_concurrency = true self @@ -1059,6 +1064,10 @@ Run `rake gems:install` to install the missing gems. true end + def default_load_application_classes + true + end + def default_whiny_nils false end diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index b4014d8..00a78a5 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -1,6 +1,7 @@ module Rails class Configuration - attr_accessor :cache_classes, :reset_subclasses, :load_paths, :eager_load_paths, :framework_paths, + attr_accessor :cache_classes, :reset_subclasses, :load_application_classes, + :load_paths, :eager_load_paths, :framework_paths, :load_once_paths, :gems_dependencies_loaded, :after_initialize_blocks, :frameworks, :framework_root_path, :root_path, :plugin_paths, :plugins, :plugin_loader, :plugin_locators, :gems, :loaded_plugins, :reload_plugins, @@ -21,6 +22,7 @@ module Rails @loaded_plugins = [] @dependency_loading = true @reset_subclasses = true + @load_application_classes = true @eager_load_paths = default_eager_load_paths @load_paths = default_load_paths @plugin_paths = default_plugin_paths @@ -88,6 +90,7 @@ module Rails def threadsafe! self.preload_frameworks = true self.cache_classes = true + self.load_application_classes = true self.dependency_loading = false self.action_controller.allow_concurrency = true self diff --git a/railties/test/initializer_test.rb b/railties/test/initializer_test.rb index 3cea2ae..1385b8e 100644 --- a/railties/test/initializer_test.rb +++ b/railties/test/initializer_test.rb @@ -49,6 +49,7 @@ class Initializer_eager_loading_Test < Test::Unit::TestCase @config = ConfigurationMock.new("") @config.cache_classes = true @config.reset_subclasses = true + @config.load_application_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 -- 1.6.0.4