aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/lib
diff options
context:
space:
mode:
authorJoshua Peek <josh@joshpeek.com>2009-06-10 23:35:34 -0500
committerJoshua Peek <josh@joshpeek.com>2009-06-10 23:36:44 -0500
commit4d703592001eef1f7e670660cd701e32105bd521 (patch)
treedb36d270b23a4a6e3a01d59e25ad92257d16ef9a /activemodel/lib
parent59c83af18b1a9189f82b9c5408cd1bad35a11eb2 (diff)
downloadrails-4d703592001eef1f7e670660cd701e32105bd521.tar.gz
rails-4d703592001eef1f7e670660cd701e32105bd521.tar.bz2
rails-4d703592001eef1f7e670660cd701e32105bd521.zip
Integrate ActiveModel::Observing into ActiveRecord
Diffstat (limited to 'activemodel/lib')
-rw-r--r--activemodel/lib/active_model.rb9
-rw-r--r--activemodel/lib/active_model/observing.rb108
2 files changed, 67 insertions, 50 deletions
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index a3545f1d53..73cee9b88f 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -27,12 +27,13 @@ require 'active_support'
module ActiveModel
autoload :Base, 'active_model/base'
- autoload :Observing, 'active_model/observing'
- autoload :Validations, 'active_model/validations'
- autoload :Errors, 'active_model/errors'
autoload :DeprecatedErrorMethods, 'active_model/deprecated_error_methods'
- autoload :TestCase, 'active_model/test_case'
+ autoload :Errors, 'active_model/errors'
+ autoload :Observer, 'active_model/observing'
+ autoload :Observing, 'active_model/observing'
autoload :StateMachine, 'active_model/state_machine'
+ autoload :TestCase, 'active_model/test_case'
+ autoload :Validations, 'active_model/validations'
autoload :ValidationsRepairHelper, 'active_model/validations_repair_helper'
end
diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb
index d3c6d8e482..d01cb737e3 100644
--- a/activemodel/lib/active_model/observing.rb
+++ b/activemodel/lib/active_model/observing.rb
@@ -3,67 +3,80 @@ require 'singleton'
module ActiveModel
module Observing
+ extend ActiveSupport::Concern
+
+ included do
+ extend Observable
+ end
+
module ClassMethods
- def observers
- @observers ||= []
- end
-
+ # Activates the observers assigned. Examples:
+ #
+ # # Calls PersonObserver.instance
+ # ActiveRecord::Base.observers = :person_observer
+ #
+ # # Calls Cacher.instance and GarbageCollector.instance
+ # ActiveRecord::Base.observers = :cacher, :garbage_collector
+ #
+ # # Same as above, just using explicit class references
+ # ActiveRecord::Base.observers = Cacher, GarbageCollector
+ #
+ # Note: Setting this does not instantiate the observers yet. +instantiate_observers+ is
+ # called during startup, and before each development request.
def observers=(*values)
@observers = values.flatten
end
-
+
+ # Gets the current observers.
+ def observers
+ @observers ||= []
+ end
+
+ # Instantiate the global Active Record observers.
def instantiate_observers
observers.each { |o| instantiate_observer(o) }
end
-
- protected
- def instantiate_observer(observer)
- # string/symbol
- if observer.respond_to?(:to_sym)
- observer = observer.to_s.camelize.constantize.instance
- elsif observer.respond_to?(:instance)
- observer.instance
- else
- raise ArgumentError, "#{observer} must be a lowercase, underscored class name (or an instance of the class itself) responding to the instance method. Example: Person.observers = :big_brother # calls BigBrother.instance"
+
+ protected
+ def instantiate_observer(observer)
+ # string/symbol
+ if observer.respond_to?(:to_sym)
+ observer = observer.to_s.camelize.constantize.instance
+ elsif observer.respond_to?(:instance)
+ observer.instance
+ else
+ raise ArgumentError, "#{observer} must be a lowercase, underscored class name (or an instance of the class itself) responding to the instance method. Example: Person.observers = :big_brother # calls BigBrother.instance"
+ end
+ end
+
+ # Notify observers when the observed class is subclassed.
+ def inherited(subclass)
+ super
+ changed
+ notify_observers :observed_class_inherited, subclass
end
- end
-
- # Notify observers when the observed class is subclassed.
- def inherited(subclass)
- super
- changed
- notify_observers :observed_class_inherited, subclass
- end
- end
-
- def self.included(receiver)
- receiver.extend Observable, ClassMethods
end
end
class Observer
include Singleton
- attr_writer :observed_classes
class << self
- attr_accessor :models
# Attaches the observer to the supplied model classes.
def observe(*models)
- @models = models.flatten
- @models.collect! { |model| model.respond_to?(:to_sym) ? model.to_s.camelize.constantize : model }
+ models.flatten!
+ models.collect! { |model| model.respond_to?(:to_sym) ? model.to_s.camelize.constantize : model }
+ define_method(:observed_classes) { models }
end
- def observed_class_name
- @observed_class_name ||=
- if guessed_name = name.scan(/(.*)Observer/)[0]
- @observed_class_name = guessed_name[0]
- end
+ def observed_classes
+ Array.wrap(observed_class)
end
# The class observed by default is inferred from the observer's class name:
- # assert_equal [Person], PersonObserver.observed_class
+ # assert_equal Person, PersonObserver.observed_class
def observed_class
- if observed_class_name
+ if observed_class_name = name[/(.*)Observer/, 1]
observed_class_name.constantize
else
nil
@@ -73,8 +86,11 @@ module ActiveModel
# Start observing the declared classes and their subclasses.
def initialize
- self.observed_classes = self.class.models if self.class.models
- observed_classes.each { |klass| klass.add_observer(self) }
+ observed_classes.each { |klass| add_observer!(klass) }
+ end
+
+ def observed_classes
+ self.class.observed_classes
end
# Send observed_method(object) if the method exists.
@@ -86,12 +102,12 @@ module ActiveModel
# Passes the new subclass.
def observed_class_inherited(subclass) #:nodoc:
self.class.observe(observed_classes + [subclass])
- subclass.add_observer(self)
+ add_observer!(subclass)
end
- protected
- def observed_classes
- @observed_classes ||= [self.class.observed_class]
- end
+ protected
+ def add_observer!(klass)
+ klass.add_observer(self)
+ end
end
-end \ No newline at end of file
+end