Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Document observers. Fixes #979

  • Loading branch information...
commit a71b4d43caf80664deedc93e5600f97acb7a908f 1 parent edec32e
@cgriego cgriego authored
Showing with 99 additions and 5 deletions.
  1. +99 −5 lib/mongoid/observer.rb
View
104 lib/mongoid/observer.rb
@@ -1,7 +1,101 @@
# encoding: utf-8
module Mongoid #:nodoc:
- # Mongoid observers hook into the lifecycle of documents.
+ # Observer classes respond to life cycle 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
+ # functionality that doesn't pertain to the core responsibility of the
+ # class. Mongoid's observers work similar to ActiveRecord's. Example:
+ #
+ # class CommentObserver < Mongoid::Observer
+ # def after_save(comment)
+ # Notifications.comment("admin@do.com", "New comment was posted", comment).deliver
+ # end
+ # end
+ #
+ # This Observer sends an email when a Comment#save is finished.
+ #
+ # class ContactObserver < Mongoid::Observer
+ # def after_create(contact)
+ # contact.logger.info('New contact added!')
+ # end
+ #
+ # def after_destroy(contact)
+ # contact.logger.warn("Contact with an id of #{contact.id} was destroyed!")
+ # end
+ # end
+ #
+ # 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):
+ #
+ # class AuditObserver < Mongoid::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:
+ #
+ # class AuditObserver < Mongoid::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.
+ #
+ # == Available callback methods
+ #
+ # * after_initialize
+ # * before_validation
+ # * after_validation
+ # * before_create
+ # * around_create
+ # * after_create
+ # * before_update
+ # * around_update
+ # * after_update
+ # * before_save
+ # * around_save
+ # * after_save
+ # * before_destroy
+ # * around_destroy
+ # * after_destroy
+ #
+ # == Storing Observers in Rails
+ #
+ # If you're using Mongoid within Rails, observer classes are usually stored in +app/models+ with the
+ # naming convention of +app/models/audit_observer.rb+.
+ #
+ # == Configuration
+ #
+ # In order to activate an observer, list it in the +config.mongoid.observers+ configuration
+ # setting in your +config/application.rb+ file.
+ #
+ # config.mongoid.observers = :comment_observer, :signup_observer
+ #
+ # Observers will not be invoked unless you define them in your application configuration.
+ #
+ # == Loading
+ #
+ # Observers register themselves with the model class that they observe, since it is the class
+ # that notifies them of events when they occur. As a side-effect, when an observer is loaded, its
+ # corresponding model class is loaded.
+ #
+ # Observers are loaded after the application initializers, so that observed models can make use
+ # of extensions. If by any chance you are using observed models in the initialization, you can
+ # still load their observers by calling +ModelObserver.instance+ before. Observers are
+ # singletons and that call instantiates and registers them.
class Observer < ActiveModel::Observer
# Instantiate the new observer. Will add all child observers as well.
@@ -9,7 +103,7 @@ class Observer < ActiveModel::Observer
# @example Instantiate the observer.
# Mongoid::Observer.new
#
- # @since 2.0.0
+ # @since 2.0.0.rc.8
def initialize
super and observed_descendants.each { |klass| add_observer!(klass) }
end
@@ -23,7 +117,7 @@ def initialize
#
# @return [ Array<Class> ] The children.
#
- # @since 2.0.0
+ # @since 2.0.0.rc.8
def observed_descendants
observed_classes.sum([]) { |klass| klass.descendants }
end
@@ -35,7 +129,7 @@ def observed_descendants
#
# @param [ Class ] klass The child observer to add.
#
- # @since 2.0.0
+ # @since 2.0.0.rc.8
def add_observer!(klass)
super and define_callbacks(klass)
end
@@ -47,7 +141,7 @@ def add_observer!(klass)
#
# @param [ Class ] klass The model to define them on.
#
- # @since 2.0.0
+ # @since 2.0.0.rc.8
def define_callbacks(klass)
tap do |observer|
observer_name = observer.class.name.underscore.gsub('/', '__')
Please sign in to comment.
Something went wrong with that request. Please try again.