lib/active_model/observing.rb in activemodel-3.0.0.beta4 vs lib/active_model/observing.rb in activemodel-3.0.pre
- old
+ new
@@ -1,15 +1,19 @@
+require 'observer'
require 'singleton'
require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/module/aliasing'
require 'active_support/core_ext/string/inflections'
-require 'active_support/core_ext/string/conversions'
module ActiveModel
module Observing
extend ActiveSupport::Concern
+ included do
+ extend Observable
+ end
+
module ClassMethods
# Activates the observers assigned. Examples:
#
# # Calls PersonObserver.instance
# ActiveRecord::Base.observers = :person_observer
@@ -18,13 +22,12 @@
# 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.
+ # 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.
@@ -35,30 +38,10 @@
# Instantiate the global Active Record observers.
def instantiate_observers
observers.each { |o| instantiate_observer(o) }
end
- def add_observer(observer)
- unless observer.respond_to? :update
- raise ArgumentError, "observer needs to respond to `update'"
- end
- @observer_instances ||= []
- @observer_instances << observer
- end
-
- def notify_observers(*arg)
- if defined? @observer_instances
- for observer in @observer_instances
- observer.update(*arg)
- end
- end
- end
-
- def count_observers
- @observer_instances.size
- end
-
protected
def instantiate_observer(observer) #:nodoc:
# string/symbol
if observer.respond_to?(:to_sym)
observer = observer.to_s.camelize.constantize.instance
@@ -70,10 +53,11 @@
end
# Notify observers when the observed class is subclassed.
def inherited(subclass)
super
+ changed
notify_observers :observed_class_inherited, subclass
end
end
private
@@ -83,10 +67,11 @@
# notify_observers(:before_save)
# ...
# notify_observers(:after_save)
# end
def notify_observers(method)
+ self.class.changed
self.class.notify_observers(method, self)
end
end
# Observer classes respond to lifecycle callbacks to implement trigger-like
@@ -115,38 +100,34 @@
#
# This Observer uses logger to log when specific callbacks are triggered.
#
# == Observing a class that can't be inferred
#
- # Observers will by default be mapped to the class with which they share a
- # name. So CommentObserver will be tied to observing Comment, ProductManagerObserver
- # to ProductManager, and so on. If you want to name your observer differently than
- # the class you're interested in observing, you can use the Observer.observe class
- # method which takes either the concrete class (Product) or a symbol for that
- # class (:product):
+ # Observers will by default be mapped to the class with which they share a name. So CommentObserver will
+ # be tied to observing Comment, ProductManagerObserver to ProductManager, and so on. If you want to name your observer
+ # differently than the class you're interested in observing, you can use the Observer.observe class method which takes
+ # either the concrete class (Product) or a symbol for that class (:product):
#
# class AuditObserver < ActiveModel::Observer
# observe :account
#
# def after_update(account)
# AuditTrail.new(account, "UPDATED")
# end
# end
#
- # If the audit observer needs to watch more than one kind of object, this can be
- # specified with multiple arguments:
+ # If the audit observer needs to watch more than one kind of object, this can be specified with multiple arguments:
#
# class AuditObserver < ActiveModel::Observer
# observe :account, :balance
#
# def after_update(record)
# AuditTrail.new(record, "UPDATED")
# end
# end
#
- # The AuditObserver will now act on both updates to Account and Balance by treating
- # them both as records.
+ # The AuditObserver will now act on both updates to Account and Balance by treating them both as records.
#
class Observer
include Singleton
class << self
@@ -161,10 +142,10 @@
#
# You can override this instead of using the +observe+ helper.
#
# class AuditObserver < ActiveModel::Observer
# def self.observed_classes
- # [Account, Balance]
+ # [AccountObserver, BalanceObserver]
# end
# end
def observed_classes
Array.wrap(observed_class)
end