Upgraded Rails and RSpec
[monkeycharger.git] / vendor / rails / activemodel / lib / active_model / observing.rb
blobdb758f518592bb083169ff4a365355e7d1b90f24
1 require 'observer'
3 module ActiveModel
4   module Observing
5     module ClassMethods
6       def observers
7         @observers ||= []
8       end
9       
10       def observers=(*values)
11         @observers = values.flatten
12       end
13       
14       def instantiate_observers
15         observers.each { |o| instantiate_observer(o) }
16       end
17     
18     protected
19       def instantiate_observer(observer)
20         # string/symbol
21         if observer.respond_to?(:to_sym)
22           observer = observer.to_s.camelize.constantize.instance
23         elsif observer.respond_to?(:instance)
24           observer.instance
25         else
26           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"
27         end
28       end
29       
30       # Notify observers when the observed class is subclassed.
31       def inherited(subclass)
32         super
33         changed
34         notify_observers :observed_class_inherited, subclass
35       end
36     end
37     
38     def self.included(receiver)
39       receiver.extend Observable, ClassMethods
40     end
41   end
43   class Observer
44     include Singleton
45     attr_writer :observed_classes
47     class << self
48       attr_accessor :models
49       # Attaches the observer to the supplied model classes.
50       def observe(*models)
51         @models = models.flatten
52         @models.collect! { |model| model.respond_to?(:to_sym) ? model.to_s.camelize.constantize : model }
53       end
55       def observed_class_name
56         @observed_class_name ||= 
57           if guessed_name = name.scan(/(.*)Observer/)[0]
58             @observed_class_name = guessed_name[0]
59           end
60       end
62       # The class observed by default is inferred from the observer's class name:
63       #   assert_equal [Person], PersonObserver.observed_class
64       def observed_class
65         if observed_class_name
66           observed_class_name.constantize
67         else
68           nil
69         end
70       end
71     end
73     # Start observing the declared classes and their subclasses.
74     def initialize
75       self.observed_classes = self.class.models if self.class.models
76       observed_classes.each { |klass| add_observer! klass }
77     end
79     # Send observed_method(object) if the method exists.
80     def update(observed_method, object) #:nodoc:
81       send(observed_method, object) if respond_to?(observed_method)
82     end
84     # Special method sent by the observed class when it is inherited.
85     # Passes the new subclass.
86     def observed_class_inherited(subclass) #:nodoc:
87       self.class.observe(observed_classes + [subclass])
88       add_observer!(subclass)
89     end
91     protected
92       def observed_classes
93         @observed_classes ||= [self.class.observed_class]
94       end
96       def add_observer!(klass)
97         klass.add_observer(self)
98       end
99   end