diff options
author | Myron Marston <myron.marston@gmail.com> | 2011-04-28 08:07:08 -0700 |
---|---|---|
committer | Myron Marston <myron.marston@gmail.com> | 2011-04-28 08:07:08 -0700 |
commit | 9a385394acd6599ff588daad491e9e07ee716091 (patch) | |
tree | 7f0fcf9c004d6faa2ebd1ac69e62e30da453b717 | |
parent | 05d4653cef1c1d8d77228de26d55cf6d6a0ce20b (diff) | |
download | rails-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.rb | 18 | ||||
-rw-r--r-- | activemodel/lib/active_model/observing.rb | 30 |
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. |