2008-06-02 08:35:38 +02:00
require 'observer'
2008-10-27 07:47:01 +01:00
require 'singleton'
require 'active_model/core'
2008-06-02 08:35:38 +02:00
module ActiveModel
module Observing
module ClassMethods
def observers
@observers || = [ ]
end
def observers = ( * values )
@observers = values . flatten
end
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 "
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 }
end
def observed_class_name
@observed_class_name || =
if guessed_name = name . scan ( / (.*)Observer / ) [ 0 ]
@observed_class_name = guessed_name [ 0 ]
end
end
# The class observed by default is inferred from the observer's class name:
# assert_equal [Person], PersonObserver.observed_class
def observed_class
if observed_class_name
observed_class_name . constantize
else
nil
end
end
end
# Start observing the declared classes and their subclasses.
def initialize
self . observed_classes = self . class . models if self . class . models
2008-10-27 07:47:01 +01:00
observed_classes . each { | klass | klass . add_observer ( self ) }
2008-06-02 08:35:38 +02:00
end
# Send observed_method(object) if the method exists.
def update ( observed_method , object ) #:nodoc:
send ( observed_method , object ) if respond_to? ( observed_method )
end
# Special method sent by the observed class when it is inherited.
# Passes the new subclass.
def observed_class_inherited ( subclass ) #:nodoc:
self . class . observe ( observed_classes + [ subclass ] )
2008-10-27 07:47:01 +01:00
subclass . add_observer ( self )
2008-06-02 08:35:38 +02:00
end
2008-10-27 07:47:01 +01:00
protected
def observed_classes
@observed_classes || = [ self . class . observed_class ]
end
2008-06-02 08:35:38 +02:00
end
end