From 948be2c998c9e3e56da742b38bc0ab57b75c8d2d Mon Sep 17 00:00:00 2001
From: David Heinemeier Hansson <david@loudthinking.com>
Date: Sun, 25 Sep 2005 08:26:29 +0000
Subject: Added new symbol-driven approach to activating observers with
 Base#observer [DHH]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@2326 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
---
 activerecord/CHANGELOG                     | 16 ++++++++++++---
 activerecord/lib/active_record.rb          |  1 +
 activerecord/lib/active_record/observer.rb | 33 +++++++++++++++++++++++++++++-
 activerecord/test/lifecycle_test.rb        |  4 ++--
 4 files changed, 48 insertions(+), 6 deletions(-)

(limited to 'activerecord')

diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index 1983a18e50..393bca06a1 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -1,10 +1,20 @@
 *SVN*
 
-* Wrap :conditions in parentheses to prevent problems with OR's #1871
+* Added new symbol-driven approach to activating observers with Base#observer [DHH]. Example:
 
-* Allow the postgresql adapter to work with the SchemaDumper.
+    ActiveRecord::Base.observer(:cacher, :garbage_collector)
+  
+  ...which is the same as doing:
+  
+    [ Cacher.instance, GarbageCollector.instance ]
+
+* Added AbstractAdapter#select_value and AbstractAdapter#select_values as convenience methods for selecting single values, instead of hashes, of the first column in a SELECT #2283 [solo@gatelys.com]
+
+* Wrap :conditions in parentheses to prevent problems with OR's #1871 [Jamis Buck]
+
+* Allow the postgresql adapter to work with the SchemaDumper. [Jamis Buck]
 
-* Add ActiveRecord::SchemaDumper for dumping a DB schema to a pure-ruby file, making it easier to consolidate large migration lists and port database schemas between databases.
+* Add ActiveRecord::SchemaDumper for dumping a DB schema to a pure-ruby file, making it easier to consolidate large migration lists and port database schemas between databases. [Jamis Buck]
 
 * Fixed migrations for Windows when using more than 10 [David Naseby]
 
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 8d50df6758..27ec3a6791 100755
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -54,6 +54,7 @@ ActiveRecord::Base.class_eval do
   include ActiveRecord::Validations
   include ActiveRecord::Locking
   include ActiveRecord::Callbacks
+  include ActiveRecord::Observing
   include ActiveRecord::Timestamp
   include ActiveRecord::Associations
   include ActiveRecord::Aggregations
diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb
index 36a9ec5d3a..36fcf021cd 100644
--- a/activerecord/lib/active_record/observer.rb
+++ b/activerecord/lib/active_record/observer.rb
@@ -1,6 +1,36 @@
 require 'singleton'
 
 module ActiveRecord
+  module Observing # :nodoc:
+    def self.append_features(base)
+      super
+      base.extend(ClassMethods)
+    end
+
+    module ClassMethods
+      # Activates the observers assigned. Examples:
+      #
+      #   # Calls PersonObserver.instance and returns the instance of that observer
+      #   ActiveRecord::Base.observer(:person_observer)
+      #
+      #   # Calls Cacher.instance and GarbageCollector.instance 
+      #   # and returns an array with instances of both
+      #   ActiveRecord::Base.observer(:cacher, :garbage_collector)
+      #
+      #   # Same as above, just using explicit class references
+      #   ActiveRecord::Base.observer(Cacher, GarbageCollector)
+      def observer(*observers)
+        observers = [ observers ].flatten.collect do |observer| 
+          observer.is_a?(Symbol) ? 
+            observer.to_s.camelize.constantize.instance :
+            observer.instance
+        end
+        
+        observers.size > 1 ? observers : observers.first
+      end
+    end
+  end
+
   # Observer classes respond to lifecycle callbacks to implement trigger-like
   # behavior outside the original class. This is a great way to reduce the
   # clutter that normally comes when the model class is burdened with
@@ -48,7 +78,8 @@ module ActiveRecord
   # == Triggering Observers
   # 
   # In order to activate an observer, you need to call Observer.instance. In Rails, this can be done in controllers
-  # using the short-hand of for example observer :comment_observer.
+  # using the short-hand of for example observer :comment_observer. Or directly from Active Record, with
+  # ActiveRecord::Base.observer(:comment_observer).
   class Observer
     include Singleton
 
diff --git a/activerecord/test/lifecycle_test.rb b/activerecord/test/lifecycle_test.rb
index d6c017672d..a373471f19 100755
--- a/activerecord/test/lifecycle_test.rb
+++ b/activerecord/test/lifecycle_test.rb
@@ -65,7 +65,7 @@ class LifecycleTest < Test::Unit::TestCase
   end
   
   def test_after_save
-    topic_observer = TopicManualObserver.instance
+    topic_observer = ActiveRecord::Base.observer(:topic_manual_observer)
 
     topic = Topic.find(1)
     topic.title = "hello"
@@ -76,7 +76,7 @@ class LifecycleTest < Test::Unit::TestCase
   end
   
   def test_observer_update_on_save
-    topic_observer = TopicManualObserver.instance
+    topic_observer = ActiveRecord::Base.observer(TopicManualObserver)
 
     topic = Topic.find(1)    
     assert topic_observer.has_been_notified?
-- 
cgit v1.2.3