aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMyron Marston <myron.marston@gmail.com>2011-04-28 08:07:08 -0700
committerMyron Marston <myron.marston@gmail.com>2011-04-28 08:07:08 -0700
commit9a385394acd6599ff588daad491e9e07ee716091 (patch)
tree7f0fcf9c004d6faa2ebd1ac69e62e30da453b717
parent05d4653cef1c1d8d77228de26d55cf6d6a0ce20b (diff)
downloadrails-9a385394acd6599ff588daad491e9e07ee716091.tar.gz
rails-9a385394acd6599ff588daad491e9e07ee716091.tar.bz2
rails-9a385394acd6599ff588daad491e9e07ee716091.zip
Fix dev env memory leaks by using AS::DescendantsTracker rather than keeping track of subclasses manually.
There's also no need to keep track of all ObserverArray instances in a hash, as this is likely to leak memory, too.
-rw-r--r--activemodel/lib/active_model/observer_array.rb18
-rw-r--r--activemodel/lib/active_model/observing.rb30
2 files changed, 12 insertions, 36 deletions
diff --git a/activemodel/lib/active_model/observer_array.rb b/activemodel/lib/active_model/observer_array.rb
index f3b5811b81..d501215dd6 100644
--- a/activemodel/lib/active_model/observer_array.rb
+++ b/activemodel/lib/active_model/observer_array.rb
@@ -4,15 +4,6 @@ module ActiveModel
# Stores the enabled/disabled state of individual observers for
# a particular model classes.
class ObserverArray < Array
- INSTANCES = Hash.new do |hash, model_class|
- hash[model_class] = new(model_class)
- end
-
- def self.for(model_class)
- return nil unless model_class < ActiveModel::Observing
- INSTANCES[model_class]
- end
-
# returns false if:
# - the ObserverArray for the given model's class has the given observer
# in its disabled_observers set.
@@ -22,7 +13,8 @@ module ActiveModel
observer_class = observer.class
loop do
- break unless array = self.for(klass)
+ break unless klass.respond_to?(:observers)
+ array = klass.observers
return false if array.disabled_observers.include?(observer_class)
klass = klass.superclass
end
@@ -90,8 +82,8 @@ module ActiveModel
end
def each_subclass_array
- model_class.subclasses.each do |subclass|
- yield self.class.for(subclass)
+ model_class.descendants.each do |subclass|
+ yield subclass.observers
end
end
@@ -102,7 +94,7 @@ module ActiveModel
yield
end
else
- observers = ActiveModel::Observer.all_observers if observers == [:all]
+ observers = ActiveModel::Observer.descendants if observers == [:all]
observers.each do |obs|
klass = observer_class_for(obs)
diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb
index ba6be46670..9ffcda8dd7 100644
--- a/activemodel/lib/active_model/observing.rb
+++ b/activemodel/lib/active_model/observing.rb
@@ -5,11 +5,16 @@ require 'active_support/core_ext/module/aliasing'
require 'active_support/core_ext/module/remove_method'
require 'active_support/core_ext/string/inflections'
require 'active_support/core_ext/enumerable'
+require 'active_support/descendants_tracker'
module ActiveModel
module Observing
extend ActiveSupport::Concern
+ included do
+ extend ActiveSupport::DescendantsTracker
+ end
+
module ClassMethods
# == Active Model Observers Activation
#
@@ -37,7 +42,7 @@ module ActiveModel
# Gets the current observers.
def observers
- @observers ||= ObserverArray.for(self)
+ @observers ||= ObserverArray.new(self)
end
# Gets the current observer instances.
@@ -70,10 +75,6 @@ module ActiveModel
observer_instances.size
end
- def subclasses
- @subclasses ||= []
- end
-
protected
def instantiate_observer(observer) #:nodoc:
# string/symbol
@@ -93,7 +94,6 @@ module ActiveModel
# Notify observers when the observed class is subclassed.
def inherited(subclass)
super
- subclasses << subclass
notify_observers :observed_class_inherited, subclass
end
end
@@ -176,6 +176,7 @@ module ActiveModel
#
class Observer
include Singleton
+ extend ActiveSupport::DescendantsTracker
class << self
# Attaches the observer to the supplied model classes.
@@ -208,23 +209,6 @@ module ActiveModel
nil
end
end
-
- def subclasses
- @subclasses ||= []
- end
-
- # List of all observer subclasses, sub-subclasses, etc.
- # Necessary so we can disable or enable all observers.
- def all_observers
- subclasses.each_with_object(subclasses.dup) do |subclass, array|
- array.concat(subclass.all_observers)
- end
- end
- end
-
- def self.inherited(subclass)
- subclasses << subclass
- super
end
# Start observing the declared classes and their subclasses.