aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activesupport/CHANGELOG2
-rw-r--r--activesupport/lib/active_support/core_ext/object_and_class.rb18
-rw-r--r--activesupport/lib/active_support/dependencies.rb2
-rw-r--r--activesupport/test/core_ext/object_and_class_ext_test.rb30
4 files changed, 40 insertions, 12 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index b72d2fd5ed..0afb5f62b1 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,6 +1,6 @@
*SVN*
-* Remove fix against memory leaks in development mode as it killed development performance on large applications (2-3s stall on Basecamp). Octopod is working on a better fix.
+* Added more efficient implementation of the development mode reset of classes #1638 [Chris McGrath]
*1.1.0*
diff --git a/activesupport/lib/active_support/core_ext/object_and_class.rb b/activesupport/lib/active_support/core_ext/object_and_class.rb
index bd67b3d1fa..4ad13265d7 100644
--- a/activesupport/lib/active_support/core_ext/object_and_class.rb
+++ b/activesupport/lib/active_support/core_ext/object_and_class.rb
@@ -1,9 +1,9 @@
class Object #:nodoc:
- def remove_subclasses_of(superclass)
- subclasses_of(superclass).each do |subclass|
- # remove_instance_variables_of(klass)
- Object.send(:remove_const, subclass) rescue nil
- end
+ def remove_subclasses_of(*superclasses)
+ subclasses_of(*superclasses).each do |subclass|
+ subclass.instance_variables.each { |v| subclass.send(:remove_instance_variable, v) }
+ Object.send(:remove_const, subclass.to_s) rescue nil
+ end
end
def remove_instance_variables_of(klass)
@@ -14,11 +14,11 @@ class Object #:nodoc:
end
end
- def subclasses_of(superclass)
+ def subclasses_of(*superclasses)
subclasses = []
ObjectSpace.each_object(Class) do |k|
- next if !k.ancestors.include?(superclass) || superclass == k || k.to_s.include?("::") || subclasses.include?(k.to_s)
- subclasses << k.to_s
+ next if (k.ancestors & superclasses).empty? || superclasses.include?(k) || k.to_s.include?("::") || subclasses.include?(k)
+ subclasses << k
end
subclasses
end
@@ -50,6 +50,6 @@ class Class #:nodoc:
end
def subclasses
- Object.subclasses_of(self)
+ Object.subclasses_of(self).map { |o| o.to_s }
end
end
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index bb46087582..c37e868b83 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -39,7 +39,7 @@ module Dependencies #:nodoc:
end
def remove_subclasses_for(*classes)
- classes.each { |klass| klass.remove_subclasses }
+ Object.remove_subclasses_of(*classes)
end
# LoadingModules implement namespace-safe dynamic loading.
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 cf75159575..29b2f2fc8b 100644
--- a/activesupport/test/core_ext/object_and_class_ext_test.rb
+++ b/activesupport/test/core_ext/object_and_class_ext_test.rb
@@ -12,6 +12,20 @@ class RemoveSubsBaseClass
end
end
class RemoveSubsSubClass < RemoveSubsBaseClass; end
+class RemoveSubsTestClass2; end
+class RemoveSubsBaseClass2
+ def self.add_ivar
+ @ivar = RemoveSubsTestClass2.new
+ end
+end
+class RemoveSubsSubClass2 < RemoveSubsBaseClass2; end
+class RemoveSubsTestClass3; end
+class RemoveSubsBaseClass3
+ def self.add_ivar
+ @ivar = RemoveSubsTestClass3.new
+ end
+end
+class RemoveSubsSubClass3 < RemoveSubsBaseClass3; end
class ClassExtTest < Test::Unit::TestCase
def test_methods
@@ -48,4 +62,18 @@ class ObjectTests < Test::Unit::TestCase
flunk("ObjectSpace still contains RemoveSubsTestClass") if o.class == RemoveSubsTestClass
end
end
-end \ No newline at end of file
+
+ def test_remove_subclasses_of_multiple_classes_unsets_ivars
+ r2 = RemoveSubsSubClass2.new
+ RemoveSubsSubClass2.add_ivar
+ r3 = RemoveSubsSubClass3.new
+ RemoveSubsSubClass3.add_ivar
+
+ Object.remove_subclasses_of(RemoveSubsBaseClass2, RemoveSubsBaseClass3)
+
+ GC.start
+ ObjectSpace.each_object do |o|
+ flunk("ObjectSpace still contains RemoveSubsTestClass") if o.class == RemoveSubsTestClass
+ end
+ end
+end