aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2006-01-29 00:37:39 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2006-01-29 00:37:39 +0000
commit01b1a8772928fbf31180341356981b95d0581413 (patch)
tree16d9939a713b79c91f5a14c799fb4e12790ecfff
parent94046542e274f76ec9d31721a73a19e4b651fbfc (diff)
downloadrails-01b1a8772928fbf31180341356981b95d0581413.tar.gz
rails-01b1a8772928fbf31180341356981b95d0581413.tar.bz2
rails-01b1a8772928fbf31180341356981b95d0581413.zip
Added reusable reloading support through the inclusion of the Relodable module that all subclasses of ActiveRecord::Base, ActiveRecord::Observer, ActiveController::Base, and ActionMailer::Base automatically gets [DHH]. Added auto-loading support for classes in modules, so Conductor::Migration will look for conductor/migration.rb and Conductor::Database::Settings will look for conductor/database/settings.rb [Nicholas Seckar]. Refactored extensions to module, class, and object in active support [DHH]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3493 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
-rw-r--r--actionmailer/lib/action_mailer/base.rb7
-rwxr-xr-xactionpack/lib/action_controller/base.rb7
-rw-r--r--actionpack/lib/action_controller/layout.rb9
-rw-r--r--actionpack/lib/action_controller/test_process.rb7
-rw-r--r--actionpack/test/template/text_helper_test.rb2
-rwxr-xr-xactiverecord/lib/active_record/base.rb1
-rw-r--r--activerecord/lib/active_record/observer.rb7
-rw-r--r--activerecord/test/class_inheritable_attributes_test.rb2
-rw-r--r--activesupport/CHANGELOG10
-rw-r--r--activesupport/lib/active_support.rb3
-rw-r--r--activesupport/lib/active_support/clean_logger.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/blank.rb16
-rw-r--r--activesupport/lib/active_support/core_ext/class.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute_accessors.rb (renamed from activesupport/lib/active_support/class_attribute_accessors.rb)0
-rw-r--r--activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb (renamed from activesupport/lib/active_support/class_inheritable_attributes.rb)0
-rw-r--r--activesupport/lib/active_support/core_ext/class/removal.rb21
-rw-r--r--activesupport/lib/active_support/core_ext/exception.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/module.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/module/attribute_accessors.rb (renamed from activesupport/lib/active_support/module_attribute_accessors.rb)0
-rw-r--r--activesupport/lib/active_support/core_ext/module/inclusion.rb15
-rw-r--r--activesupport/lib/active_support/core_ext/object.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/object/extending.rb (renamed from activesupport/lib/active_support/core_ext/object_and_class.rb)47
-rw-r--r--activesupport/lib/active_support/core_ext/object/misc.rb16
-rw-r--r--activesupport/lib/active_support/dependencies.rb65
-rw-r--r--activesupport/lib/active_support/reloadable.rb4
-rw-r--r--activesupport/test/autoloading_fixtures/a/b.rb2
-rw-r--r--activesupport/test/autoloading_fixtures/a/c/d.rb2
-rw-r--r--activesupport/test/autoloading_fixtures/e.rb2
-rw-r--r--activesupport/test/class_inheritable_attributes_test.rb2
-rw-r--r--activesupport/test/core_ext/blank_test.rb2
-rw-r--r--activesupport/test/core_ext/class_test.rb37
-rw-r--r--activesupport/test/core_ext/module_test.rb51
-rw-r--r--activesupport/test/core_ext/object_and_class_ext_test.rb3
-rw-r--r--activesupport/test/dependencies_test.rb17
-rw-r--r--activesupport/test/option_merger_test.rb2
-rw-r--r--railties/lib/dispatcher.rb3
36 files changed, 298 insertions, 74 deletions
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 8659489808..39fa1e4aac 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -121,6 +121,13 @@ module ActionMailer
class Base
include AdvAttrAccessor, PartContainer
+ # Action Mailer subclasses should be reloaded by the dispatcher in Rails
+ # when Dependencies.mechanism = :load.
+ def self.inherited(child) #:nodoc:
+ child.send :include, Reloadable
+ super
+ end
+
private_class_method :new #:nodoc:
cattr_accessor :template_root
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 7f8ff5ed09..43f948e73d 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -224,6 +224,13 @@ module ActionController #:nodoc:
# FCGI.each_cgi{ |cgi| WeblogController.process_cgi(cgi) }
class Base
DEFAULT_RENDER_STATUS_CODE = "200 OK"
+
+ # Action Controller subclasses should be reloaded by the dispatcher in Rails
+ # when Dependencies.mechanism = :load.
+ def self.inherited(child) #:nodoc:
+ child.send :include, Reloadable
+ super
+ end
# Determines whether the view has access to controller internals @request, @response, @session, and @template.
# By default, it does.
diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/layout.rb
index cc153c45a7..f2a5b97bf1 100644
--- a/actionpack/lib/action_controller/layout.rb
+++ b/actionpack/lib/action_controller/layout.rb
@@ -1,16 +1,16 @@
module ActionController #:nodoc:
module Layout #:nodoc:
- def self.append_features(base)
- super
+ def self.included(base)
+ base.extend(ClassMethods)
base.class_eval do
alias_method :render_with_no_layout, :render
alias_method :render, :render_with_a_layout
class << self
alias_method :inherited_without_layout, :inherited
+ alias_method :inherited, :inherited_with_layout
end
end
- base.extend(ClassMethods)
end
# Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in
@@ -172,8 +172,9 @@ module ActionController #:nodoc:
end
private
- def inherited(child)
+ def inherited_with_layout(child)
inherited_without_layout(child)
+ child.send :include, Reloadable
layout_match = child.name.underscore.sub(/_controller$/, '')
child.layout(layout_match) unless layout_list.grep(%r{layouts/#{layout_match}\.[a-z][0-9a-z]*$}).empty?
end
diff --git a/actionpack/lib/action_controller/test_process.rb b/actionpack/lib/action_controller/test_process.rb
index 289ab3d5e7..caba4bfb39 100644
--- a/actionpack/lib/action_controller/test_process.rb
+++ b/actionpack/lib/action_controller/test_process.rb
@@ -333,6 +333,13 @@ module ActionController #:nodoc:
end
end
+ def build_request_uri(action, parameters)
+ options = @controller.send(:rewrite_options, parameters)
+ options.update(:only_path => true, :action => action)
+ url = ActionController::UrlRewriter.new(@request, parameters)
+ @request.set_REQUEST_URI(url.rewrite(options))
+ end
+
def session
@response.session
end
diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb
index b323568068..d1ef946f29 100644
--- a/actionpack/test/template/text_helper_test.rb
+++ b/actionpack/test/template/text_helper_test.rb
@@ -3,7 +3,7 @@ require "#{File.dirname(__FILE__)}/../testing_sandbox"
require File.dirname(__FILE__) + '/../../lib/action_view/helpers/text_helper'
require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/numeric' # for human_size
require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/hash' # for stringify_keys
-require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/object_and_class.rb' # for blank?
+require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/object.rb' # for blank?
class TextHelperTest < Test::Unit::TestCase
include ActionView::Helpers::TextHelper
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index d05e3c6cae..f134402c58 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -244,6 +244,7 @@ module ActiveRecord #:nodoc:
cattr_accessor :logger
def self.inherited(child) #:nodoc:
+ child.send :include, Reloadable
@@subclasses[self] ||= []
@@subclasses[self] << child
super
diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb
index 7d33509c8c..d43909c3c5 100644
--- a/activerecord/lib/active_record/observer.rb
+++ b/activerecord/lib/active_record/observer.rb
@@ -81,6 +81,13 @@ module ActiveRecord
class Observer
include Singleton
+ # Observer subclasses should be reloaded by the dispatcher in Rails
+ # when Dependencies.mechanism = :load.
+ def self.inherited(child) #:nodoc:
+ child.send :include, Reloadable
+ super
+ end
+
# Attaches the observer to the supplied model classes.
def self.observe(*models)
define_method(:observed_class) { models }
diff --git a/activerecord/test/class_inheritable_attributes_test.rb b/activerecord/test/class_inheritable_attributes_test.rb
index 3419ffbd9a..a3f94e3abb 100644
--- a/activerecord/test/class_inheritable_attributes_test.rb
+++ b/activerecord/test/class_inheritable_attributes_test.rb
@@ -1,6 +1,6 @@
require 'test/unit'
require 'abstract_unit'
-require 'active_support/class_inheritable_attributes'
+require 'active_support/core_ext/class/inheritable_attributes'
class A
include ClassInheritableAttributes
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index c448efbefb..d1e9c1c331 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,15 @@
*SVN*
+* Added reusable reloading support through the inclusion of the Relodable module that all subclasses of ActiveRecord::Base, ActiveRecord::Observer, ActiveController::Base, and ActionMailer::Base automatically gets. This means that these classes will be reloaded by the dispatcher when Dependencies.mechanism = :load. You can make your own models reloadable easily:
+
+ class Setting
+ include Reloadable
+ end
+
+ Reloading a class is done by removing its constant which will cause it to be loaded again on the next reference. [DHH]
+
+* Added auto-loading support for classes in modules, so Conductor::Migration will look for conductor/migration.rb and Conductor::Database::Settings will look for conductor/database/settings.rb [Nicholas Seckar]
+
* Add Object#instance_exec, like instance_eval but passes its arguments to the block. (Active Support will not override the Ruby 1.9 implementation of this method.) [Sam Stephenson]
* Add Proc#bind(object) for changing a proc or block's self by returning a Method bound to the given object. Based on why the lucky stiff's "cloaker" method. [Sam Stephenson]
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index f498a8e1f5..7bd74101f5 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -23,13 +23,12 @@
$:.unshift(File.dirname(__FILE__))
-require 'active_support/class_attribute_accessors'
-require 'active_support/class_inheritable_attributes'
require 'active_support/inflector'
require 'active_support/core_ext'
require 'active_support/clean_logger'
require 'active_support/dependencies'
+require 'active_support/reloadable'
require 'active_support/ordered_options'
require 'active_support/option_merger'
diff --git a/activesupport/lib/active_support/clean_logger.rb b/activesupport/lib/active_support/clean_logger.rb
index 2730ef9008..376896cb3c 100644
--- a/activesupport/lib/active_support/clean_logger.rb
+++ b/activesupport/lib/active_support/clean_logger.rb
@@ -1,5 +1,5 @@
require 'logger'
-require File.dirname(__FILE__) + '/class_attribute_accessors'
+require File.dirname(__FILE__) + '/core_ext/class/attribute_accessors'
class Logger #:nodoc:
cattr_accessor :silencer
diff --git a/activesupport/lib/active_support/core_ext/blank.rb b/activesupport/lib/active_support/core_ext/blank.rb
index 791cdc5705..f7fbea3e89 100644
--- a/activesupport/lib/active_support/core_ext/blank.rb
+++ b/activesupport/lib/active_support/core_ext/blank.rb
@@ -1,4 +1,16 @@
-# The methods here are provided to speed up function blank? in class Object
+class Object #:nodoc:
+ # "", " ", nil, [], and {} are blank
+ def blank?
+ if respond_to?(:empty?) && respond_to?(:strip)
+ empty? or strip.empty?
+ elsif respond_to?(:empty?)
+ empty?
+ else
+ !self
+ end
+ end
+end
+
class NilClass #:nodoc:
def blank?
true
@@ -35,4 +47,4 @@ class Numeric #:nodoc:
def blank?
false
end
-end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/core_ext/class.rb b/activesupport/lib/active_support/core_ext/class.rb
new file mode 100644
index 0000000000..7bacdb3903
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/class.rb
@@ -0,0 +1,3 @@
+require File.dirname(__FILE__) + '/class/attribute_accessors'
+require File.dirname(__FILE__) + '/class/inheritable_attributes'
+require File.dirname(__FILE__) + '/class/removal' \ No newline at end of file
diff --git a/activesupport/lib/active_support/class_attribute_accessors.rb b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
index 93a7d48f69..93a7d48f69 100644
--- a/activesupport/lib/active_support/class_attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute_accessors.rb
diff --git a/activesupport/lib/active_support/class_inheritable_attributes.rb b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
index 2e70a64436..2e70a64436 100644
--- a/activesupport/lib/active_support/class_inheritable_attributes.rb
+++ b/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb
diff --git a/activesupport/lib/active_support/core_ext/class/removal.rb b/activesupport/lib/active_support/core_ext/class/removal.rb
new file mode 100644
index 0000000000..8fc4d728b3
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/class/removal.rb
@@ -0,0 +1,21 @@
+class Class #:nodoc:
+ def remove_subclasses
+ Object.remove_subclasses_of(self)
+ end
+
+ def subclasses
+ Object.subclasses_of(self).map { |o| o.to_s }
+ end
+
+ def remove_class(klass)
+ if klass.to_s.include? "::"
+ modules = klass.to_s.split("::")
+ final_klass = modules.pop
+
+ final_module = modules.inject(Object) { |final_type, part| final_type.const_get(part) }
+ final_module.send(:remove_const, final_klass) rescue nil
+ else
+ Object.send(:remove_const, klass.to_s) rescue nil
+ end
+ end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/core_ext/exception.rb b/activesupport/lib/active_support/core_ext/exception.rb
index 2541f37495..0b65af7bf8 100644
--- a/activesupport/lib/active_support/core_ext/exception.rb
+++ b/activesupport/lib/active_support/core_ext/exception.rb
@@ -1,5 +1,4 @@
class Exception
-
alias :clean_message :message
TraceSubstitutions = []
diff --git a/activesupport/lib/active_support/core_ext/module.rb b/activesupport/lib/active_support/core_ext/module.rb
new file mode 100644
index 0000000000..0f46631e65
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/module.rb
@@ -0,0 +1,2 @@
+require File.dirname(__FILE__) + '/module/inclusion'
+require File.dirname(__FILE__) + '/module/attribute_accessors' \ No newline at end of file
diff --git a/activesupport/lib/active_support/module_attribute_accessors.rb b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
index fe4f8a4fc0..fe4f8a4fc0 100644
--- a/activesupport/lib/active_support/module_attribute_accessors.rb
+++ b/activesupport/lib/active_support/core_ext/module/attribute_accessors.rb
diff --git a/activesupport/lib/active_support/core_ext/module/inclusion.rb b/activesupport/lib/active_support/core_ext/module/inclusion.rb
new file mode 100644
index 0000000000..124c4551bc
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/module/inclusion.rb
@@ -0,0 +1,15 @@
+class Module
+ def remove_classes_including
+ included_in_classes.each { |klass| Class.remove_class(klass) }
+ end
+
+ def included_in_classes
+ classes = []
+ ObjectSpace.each_object(Class) { |k| classes << k if k.included_modules.include?(self) }
+
+ classes.reverse.inject([]) do |unique_classes, klass|
+ unique_classes << klass unless unique_classes.collect { |k| k.to_s }.include?(klass.to_s)
+ unique_classes
+ end
+ end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/core_ext/object.rb b/activesupport/lib/active_support/core_ext/object.rb
new file mode 100644
index 0000000000..3dd6deaba1
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/object.rb
@@ -0,0 +1,2 @@
+require File.dirname(__FILE__) + '/object/extending'
+require File.dirname(__FILE__) + '/object/misc' \ No newline at end of file
diff --git a/activesupport/lib/active_support/core_ext/object_and_class.rb b/activesupport/lib/active_support/core_ext/object/extending.rb
index d44afbd839..8c638f83c2 100644
--- a/activesupport/lib/active_support/core_ext/object_and_class.rb
+++ b/activesupport/lib/active_support/core_ext/object/extending.rb
@@ -4,7 +4,7 @@ class Object #:nodoc:
Object.send(:remove_const, subclass.to_s) rescue nil
end
end
-
+
def subclasses_of(*superclasses)
subclasses = []
ObjectSpace.each_object(Class) do |k|
@@ -20,41 +20,16 @@ class Object #:nodoc:
end
def copy_instance_variables_from(object, exclude = [])
- exclude += object.protected_instance_variables if
- object.respond_to? :protected_instance_variables
+ exclude += object.protected_instance_variables if object.respond_to? :protected_instance_variables
instance_variables = object.instance_variables - exclude.map { |name| name.to_s }
- instance_variables.each do |name|
- instance_variable_set name, object.instance_variable_get(name)
- end
+ instance_variables.each { |name| instance_variable_set(name, object.instance_variable_get(name)) }
end
def extend_with_included_modules_from(object)
object.extended_by.each { |mod| extend mod }
end
-
- # "", " ", nil, [], and {} are blank
- def blank?
- if respond_to?(:empty?) && respond_to?(:strip)
- empty? or strip.empty?
- elsif respond_to?(:empty?)
- empty?
- else
- !self
- end
- end
- def suppress(*exception_classes)
- begin yield
- rescue Exception => e
- raise unless exception_classes.any? {|cls| e.kind_of? cls}
- end
- end
-
- def with_options(options)
- yield ActiveSupport::OptionMerger.new(self, options)
- end
-
def instance_values
instance_variables.inject({}) do |values, name|
values[name[1..-1]] = instance_variable_get(name)
@@ -62,23 +37,9 @@ class Object #:nodoc:
end
end
- def to_json
- ActiveSupport::JSON.encode(self)
- end
-
unless defined? instance_exec # 1.9
def instance_exec(*arguments, &block)
block.bind(self)[*arguments]
end
end
-end
-
-class Class #:nodoc:
- def remove_subclasses
- Object.remove_subclasses_of(self)
- end
-
- def subclasses
- Object.subclasses_of(self).map { |o| o.to_s }
- end
-end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/core_ext/object/misc.rb b/activesupport/lib/active_support/core_ext/object/misc.rb
new file mode 100644
index 0000000000..f599eee6f0
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/object/misc.rb
@@ -0,0 +1,16 @@
+class Object #:nodoc:
+ def with_options(options)
+ yield ActiveSupport::OptionMerger.new(self, options)
+ end
+
+ def to_json
+ ActiveSupport::JSON.encode(self)
+ end
+
+ def suppress(*exception_classes)
+ begin yield
+ rescue Exception => e
+ raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
+ end
+ end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 8d1288cd96..37a3f4acb3 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -1,5 +1,5 @@
require 'set'
-require File.dirname(__FILE__) + '/module_attribute_accessors'
+require File.dirname(__FILE__) + '/core_ext/module/attribute_accessors'
require File.dirname(__FILE__) + '/core_ext/load_error'
require File.dirname(__FILE__) + '/core_ext/kernel'
@@ -69,10 +69,6 @@ module Dependencies #:nodoc:
history << file_name
end
- def remove_subclasses_for(*classes)
- Object.remove_subclasses_of(*classes)
- end
-
# LoadingModules implement namespace-safe dynamic loading.
# They support automatic loading via const_missing, allowing contained items to be automatically
# loaded when required. No extra syntax is required, as expressions such as Controller::Admin::UserController
@@ -211,27 +207,70 @@ Object.send(:define_method, :require_association) { |file_name| Dependencies.ass
class Module #:nodoc:
# Rename the original handler so we can chain it to the new one
alias :rails_original_const_missing :const_missing
-
+
+ def parent
+ parent_name = name.split('::')[0..-2] * '::'
+ parent_name.empty? ? Object : parent_name.constantize
+ end
+
+ def as_load_path
+ if self == Object || self == Kernel
+ ''
+ elsif is_a? Class
+ parent == self ? '' : parent.as_load_path
+ else
+ name.split('::').collect do |word|
+ word.underscore
+ end * '/'
+ end
+ end
+
# Use const_missing to autoload associations so we don't have to
# require_association when using single-table inheritance.
def const_missing(class_id)
- if Object.const_defined?(:Controllers) and Object::Controllers.const_available?(class_id)
+ if Object.const_defined?(:Controllers) && Object::Controllers.const_available?(class_id)
return Object::Controllers.const_get(class_id)
end
file_name = class_id.to_s.demodulize.underscore
+ file_path = as_load_path.empty? ? file_name : "#{as_load_path}/#{file_name}"
begin
- require_dependency(file_name)
- raise NameError.new("uninitialized constant #{class_id}") unless Object.const_defined?(class_id)
- return Object.const_get(class_id)
+ require_dependency(file_path)
+ brief_name = self == Object ? '' : "#{name}::"
+ raise NameError.new("uninitialized constant #{brief_name}#{class_id}") unless const_defined?(class_id)
+ return const_get(class_id)
rescue MissingSourceFile => e
- # Convert the exception to a NameError only if the file we are looking for is the missing one.
- raise unless e.is_missing? file_name
+ # Re-raise the error if it does not concern the file we were trying to load.
+ raise unless e.is_missing? file_path
+
+ # Look for a directory in the load path that we ought to load.
+ if $LOAD_PATH.any? { |base| File.directory? "#{base}/#{file_path}" }
+ mod = Module.new
+ const_set class_id, mod # Create the new module
+ return mod
+ end
+
+ if parent && parent != self
+ suppress(NameError) do
+ return parent.send(:const_missing, class_id)
+ end
+ end
+
raise NameError.new("uninitialized constant #{class_id}").copy_blame!(e)
end
end
end
+class Class
+ def const_missing(class_id)
+ if [Object, Kernel].include?(self) || parent == self
+ super
+ else
+ parent.send :const_missing, class_id
+ end
+ end
+end
+
class Object #:nodoc:
def load(file, *extras)
super(file, *extras)
@@ -267,4 +306,4 @@ class Exception #:nodoc:
@blamed_files = exc.blamed_files.clone
self
end
-end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/reloadable.rb b/activesupport/lib/active_support/reloadable.rb
new file mode 100644
index 0000000000..fca397afeb
--- /dev/null
+++ b/activesupport/lib/active_support/reloadable.rb
@@ -0,0 +1,4 @@
+# Classes that include this module will automatically be reloaded
+# by the Rails dispatcher when Dependencies.mechanism = :load.
+module Reloadable
+end \ No newline at end of file
diff --git a/activesupport/test/autoloading_fixtures/a/b.rb b/activesupport/test/autoloading_fixtures/a/b.rb
new file mode 100644
index 0000000000..9c9e6454cf
--- /dev/null
+++ b/activesupport/test/autoloading_fixtures/a/b.rb
@@ -0,0 +1,2 @@
+class A::B
+end \ No newline at end of file
diff --git a/activesupport/test/autoloading_fixtures/a/c/d.rb b/activesupport/test/autoloading_fixtures/a/c/d.rb
new file mode 100644
index 0000000000..0f40d6fbc4
--- /dev/null
+++ b/activesupport/test/autoloading_fixtures/a/c/d.rb
@@ -0,0 +1,2 @@
+class A::C::D
+end \ No newline at end of file
diff --git a/activesupport/test/autoloading_fixtures/e.rb b/activesupport/test/autoloading_fixtures/e.rb
new file mode 100644
index 0000000000..2f59e4fb75
--- /dev/null
+++ b/activesupport/test/autoloading_fixtures/e.rb
@@ -0,0 +1,2 @@
+class E
+end \ No newline at end of file
diff --git a/activesupport/test/class_inheritable_attributes_test.rb b/activesupport/test/class_inheritable_attributes_test.rb
index 9a472eacd2..36914e2bbf 100644
--- a/activesupport/test/class_inheritable_attributes_test.rb
+++ b/activesupport/test/class_inheritable_attributes_test.rb
@@ -1,5 +1,5 @@
require 'test/unit'
-require File.dirname(__FILE__) + '/../lib/active_support/class_inheritable_attributes'
+require File.dirname(__FILE__) + '/../lib/active_support/core_ext/class/inheritable_attributes'
class ClassInheritableAttributesTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/test/core_ext/blank_test.rb b/activesupport/test/core_ext/blank_test.rb
index 2aba73a008..ff7345e774 100644
--- a/activesupport/test/core_ext/blank_test.rb
+++ b/activesupport/test/core_ext/blank_test.rb
@@ -1,5 +1,5 @@
require 'test/unit'
-require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/object_and_class'
+require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/object'
require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/blank'
class BlankTest < Test::Unit::TestCase
diff --git a/activesupport/test/core_ext/class_test.rb b/activesupport/test/core_ext/class_test.rb
new file mode 100644
index 0000000000..6e956fa45d
--- /dev/null
+++ b/activesupport/test/core_ext/class_test.rb
@@ -0,0 +1,37 @@
+require 'test/unit'
+require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/class'
+
+class A
+end
+
+module X
+ class B
+ end
+end
+
+module Y
+ module Z
+ class C
+ end
+ end
+end
+
+class ClassTest < Test::Unit::TestCase
+ def test_removing_class_in_root_namespace
+ assert A.is_a?(Class)
+ Class.remove_class(A)
+ assert_raises(NameError) { A.is_a?(Class) }
+ end
+
+ def test_removing_class_in_one_level_namespace
+ assert X::B.is_a?(Class)
+ Class.remove_class(X::B)
+ assert_raises(NameError) { X::B.is_a?(Class) }
+ end
+
+ def test_removing_class_in_two_level_namespace
+ assert Y::Z::C.is_a?(Class)
+ Class.remove_class(Y::Z::C)
+ assert_raises(NameError) { Y::Z::C.is_a?(Class) }
+ end
+end
diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb
new file mode 100644
index 0000000000..3d11f1001f
--- /dev/null
+++ b/activesupport/test/core_ext/module_test.rb
@@ -0,0 +1,51 @@
+require 'test/unit'
+require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/class'
+require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/module'
+
+module One
+end
+
+class Ab
+ include One
+end
+
+module Xy
+ class Bc
+ include One
+ end
+end
+
+module Yz
+ module Zy
+ class Cd
+ include One
+ end
+ end
+end
+
+class De
+end
+
+class ModuleTest < Test::Unit::TestCase
+ def test_included_in_classes
+ assert One.included_in_classes.include?(Ab)
+ assert One.included_in_classes.include?(Xy::Bc)
+ assert One.included_in_classes.include?(Yz::Zy::Cd)
+ assert !One.included_in_classes.include?(De)
+ end
+
+ def test_remove_classes_including
+ assert Ab.is_a?(Class)
+ assert Xy::Bc.is_a?(Class)
+ assert Yz::Zy::Cd.is_a?(Class)
+ assert De.is_a?(Class)
+
+ One.remove_classes_including
+
+ assert_raises(NameError) { Ae.is_a?(Class) }
+ assert_raises(NameError) { Xy::Bc.is_a?(Class) }
+ assert_raises(NameError) { Yz::Zy::Cd.is_a?(Class) }
+
+ assert De.is_a?(Class)
+ end
+end \ No newline at end of file
diff --git a/activesupport/test/core_ext/object_and_class_ext_test.rb b/activesupport/test/core_ext/object_and_class_ext_test.rb
index fc19183ede..5d7a06d08d 100644
--- a/activesupport/test/core_ext/object_and_class_ext_test.rb
+++ b/activesupport/test/core_ext/object_and_class_ext_test.rb
@@ -1,5 +1,6 @@
require 'test/unit'
-require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/object_and_class'
+require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/object'
+require File.dirname(__FILE__) + '/../../lib/active_support/core_ext/class'
class ClassA; end
class ClassB < ClassA; end
diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb
index ab28c4668e..953a64a0ef 100644
--- a/activesupport/test/dependencies_test.rb
+++ b/activesupport/test/dependencies_test.rb
@@ -1,5 +1,6 @@
require 'test/unit'
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib/active_support/'
+require 'core_ext/string'
require 'dependencies'
class DependenciesTest < Test::Unit::TestCase
@@ -99,4 +100,20 @@ class DependenciesTest < Test::Unit::TestCase
$LOAD_PATH.shift
Dependencies.mechanism = old_mechanism
end
+
+ def test_as_load_path
+ assert_equal '', DependenciesTest.as_load_path
+ end
+
+ def test_module_loading
+ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/autoloading_fixtures"
+ old_mechanism, Dependencies.mechanism = Dependencies.mechanism, :load
+
+ assert_kind_of Module, A
+ assert_kind_of Class, A::B
+ assert_kind_of Class, A::C::D
+ ensure
+ $LOAD_PATH.shift
+ Dependencies.mechanism = old_mechanism
+ end
end
diff --git a/activesupport/test/option_merger_test.rb b/activesupport/test/option_merger_test.rb
index baa2cd30f3..f5287d5725 100644
--- a/activesupport/test/option_merger_test.rb
+++ b/activesupport/test/option_merger_test.rb
@@ -2,7 +2,7 @@ require 'test/unit'
unless defined? ActiveSupport::OptionMerger
require File.dirname(__FILE__) + '/../lib/active_support/option_merger'
- require File.dirname(__FILE__) + '/../lib/active_support/core_ext/object_and_class'
+ require File.dirname(__FILE__) + '/../lib/active_support/core_ext/object'
end
class OptionMergerTest < Test::Unit::TestCase
diff --git a/railties/lib/dispatcher.rb b/railties/lib/dispatcher.rb
index 29dae09b55..7f03294860 100644
--- a/railties/lib/dispatcher.rb
+++ b/railties/lib/dispatcher.rb
@@ -53,8 +53,7 @@ class Dispatcher
Controllers.clear!
Dependencies.clear
ActiveRecord::Base.reset_subclasses
- Dependencies.remove_subclasses_for(ActiveRecord::Base, ActiveRecord::Observer, ActionController::Base)
- Dependencies.remove_subclasses_for(ActionMailer::Base) if defined?(ActionMailer::Base)
+ Reloadable.remove_classes_including
end
private