diff options
Diffstat (limited to 'activerecord/lib/active_record/observer.rb')
-rw-r--r-- | activerecord/lib/active_record/observer.rb | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb new file mode 100644 index 0000000000..ceba78b043 --- /dev/null +++ b/activerecord/lib/active_record/observer.rb @@ -0,0 +1,71 @@ +require 'singleton' + +module ActiveRecord + # Observers can be programmed to react to lifecycle callbacks in another class 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 excess responsibility that doesn't pertain to + # the core and nature of the class. Example: + # + # class CommentObserver < ActiveRecord::Observer + # def after_save(comment) + # Notifications.deliver_comment("admin@do.com", "New comment was posted", comment) + # end + # end + # + # This Observer is triggered when a Comment#save is finished and sends a notification about it to the administrator. + # + # == Observing a class that can't be infered + # + # 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 + # something else than the class you're interested in observing, you can implement the observed_class class method. Like this: + # + # class AuditObserver < ActiveRecord::Observer + # def self.observed_class() Account end + # def after_update(account) + # AuditTrail.new(account, "UPDATED") + # end + # end + # + # == Observing multiple classes at once + # + # If the audit observer needs to watch more than one kind of object, this can be specified in an array, like this: + # + # class AuditObserver < ActiveRecord::Observer + # def self.observed_class() [ Account, Balance ] end + # 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 observer can implement callback methods for each of the methods described in the Callbacks module. + class Observer + include Singleton + + def initialize + [ observed_class ].flatten.each do |klass| + klass.add_observer(self) + klass.send(:define_method, :after_find) unless klass.respond_to?(:after_find) + end + end + + def update(callback_method, object) + send(callback_method, object) if respond_to?(callback_method) + end + + private + def observed_class + if self.class.respond_to? "observed_class" + self.class.observed_class + else + Object.const_get(infer_observed_class_name) + end + end + + def infer_observed_class_name + self.class.name.scan(/(.*)Observer/)[0][0] + end + end +end
\ No newline at end of file |