Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added documentation for Observers in the AR validations and callbacks…

… guides
  • Loading branch information...
commit 4d177a5939fedd31abf29129c521b03f5f6cbd44 1 parent e264337
@cassiomarques cassiomarques authored
View
53 railties/doc/guides/html/activerecord_validations_callbacks.html
@@ -304,6 +304,16 @@ <h2 id="site_title_tagline">Sustainable productivity for web-application develop
<a href="#_callback_classes">Callback classes</a>
</li>
<li>
+ <a href="#_observers">Observers</a>
+ <ul>
+
+ <li><a href="#_registering_observers">Registering observers</a></li>
+
+ <li><a href="#_where_to_put_the_observers_source_files">Where to put the observers' source files</a></li>
+
+ </ul>
+ </li>
+ <li>
<a href="#_changelog">Changelog</a>
</li>
</ol>
@@ -1135,7 +1145,48 @@ <h2 id="_callback_classes">11. Callback classes</h2>
</tt></pre></div></div>
<div class="para"><p>You can declare as many callbacks as you want inside your callback classes.</p></div>
</div>
-<h2 id="_changelog">12. Changelog</h2>
+<h2 id="_observers">12. Observers</h2>
+<div class="sectionbody">
+<div class="para"><p>Active Record callbacks are a powerful feature, but they can pollute your model implementation with code that's not directly related to the model's purpose. In object-oriented software, it's always a good idea to design your classes with a single responsability in the whole system. For example, it wouldn't make much sense to have a <tt>User</tt> model with a method that writes data about a login attempt to a log file. Whenever you're using callbacks to write code that's not directly related to your model class purposes, it may be a good moment to create an Observer.</p></div>
+<div class="para"><p>An Active Record Observer is an object that links itself to a model and register it's methods for callbacks. Your model's implementation remain clean, while you can reuse the code in the Observer to add behaviuor to more than one model class. Ok, you may say that we can also do that using callback classes, but it would still force us to add code to our model's implementation.</p></div>
+<div class="para"><p>Observer classes are subclasses of the <tt>ActiveRecord::Observer</tt> class. When this class is subclassed, Active Record will look at the name of the new class and then strip the <em>Observer</em> part to find the name of the Active Record class to observe.</p></div>
+<div class="para"><p>Consider a <tt>Registration</tt> model, where we want to send an email everytime a new registration is created. Since sending emails is not directly related to our model's purpose, we could create an Observer to do just that:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> RegistrationObserver <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Observer
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> after_create<span style="color: #990000">(</span>model<span style="color: #990000">)</span>
+ <span style="font-style: italic"><span style="color: #9A1900"># code to send registration confirmation emails...</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Like in callback classes, the observer's methods receive the observed model as a parameter.</p></div>
+<div class="para"><p>Sometimes using the ModelName + Observer naming convention won't be the best choice, mainly when you want to use the same observer for more than one model class. It's possible to explicity specify the models that our observer should observe.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Auditor <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Observer
+ observe User<span style="color: #990000">,</span> Registration<span style="color: #990000">,</span> Invoice
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_registering_observers">12.1. Registering observers</h3>
+<div class="para"><p>If you payed attention, you may be wondering where Active Record Observers are referenced in our applications, so they get instantiate and begin to interact with our models. For observers to work we need to register then in our application's <strong>config/environment.rb</strong> file. In this file there is a commented out line where we can define the observers that our application should load at start-up.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># Activate observers that should always be running</span></span>
+config<span style="color: #990000">.</span>active_record<span style="color: #990000">.</span>observers <span style="color: #990000">=</span> <span style="color: #990000">:</span>registration_observer<span style="color: #990000">,</span> <span style="color: #990000">:</span>auditor
+</tt></pre></div></div>
+<h3 id="_where_to_put_the_observers_source_files">12.2. Where to put the observers' source files</h3>
+<div class="para"><p>By convention, you should always save your observers' source files inside <strong>app/models</strong>.</p></div>
+</div>
+<h2 id="_changelog">13. Changelog</h2>
<div class="sectionbody">
<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213/tickets/26-active-record-validations-and-callbacks">http://rails.lighthouseapp.com/projects/16213/tickets/26-active-record-validations-and-callbacks</a></p></div>
</div>
View
50 railties/doc/guides/source/activerecord_validations_callbacks.txt
@@ -7,7 +7,7 @@ After reading this guide and trying out the presented concepts, we hope that you
* Correctly use all the built-in Active Record validation helpers
* Create your own custom validation methods
-* Work with the error messages generated by the validation proccess
+* Work with the error messages generated by the validation process
* Register callback methods that will execute custom operations during your objects lifecycle, for example before/after they are saved.
* Create special classes that encapsulate common behaviour for your callbacks
* Create Observers - classes with callback methods specific for each of your models, keeping the callback code outside your models' declarations.
@@ -303,7 +303,7 @@ There are some common options that all the validation helpers can use. Here they
=== The +:allow_nil+ option
-You may use the +:allow_nil+ option everytime you just want to trigger a validation if the value being validated is not +nil+. You may be asking yourself if it makes any sense to use +:allow_nil+ and +validates_presence_of+ together. Well, it does. Remember, validation will be skipped only for +nil+ attributes, but empty strings are not considered +nil+.
+You may use the +:allow_nil+ option everytime you want to trigger a validation only if the value being validated is not +nil+. You may be asking yourself if it makes any sense to use +:allow_nil+ and +validates_presence_of+ together. Well, it does. Remember, validation will be skipped only for +nil+ attributes, but empty strings are not considered +nil+.
[source, ruby]
------------------------------------------------------------------
@@ -487,7 +487,7 @@ In order to use the available callbacks, you need to registrate them. There are
=== Registering callbacks by overriding the callback methods
-You can specify the callback method direcly, by overriding it. Let's see how it works using the +before_validation+ callback, which will surprisingly run right before any validation is done.
+You can specify the callback method directly, by overriding it. Let's see how it works using the +before_validation+ callback, which will surprisingly run right before any validation is done.
[source, ruby]
------------------------------------------------------------------
@@ -635,6 +635,50 @@ end
You can declare as many callbacks as you want inside your callback classes.
+== Observers
+
+Active Record callbacks are a powerful feature, but they can pollute your model implementation with code that's not directly related to the model's purpose. In object-oriented software, it's always a good idea to design your classes with a single responsability in the whole system. For example, it wouldn't make much sense to have a +User+ model with a method that writes data about a login attempt to a log file. Whenever you're using callbacks to write code that's not directly related to your model class purposes, it may be a good moment to create an Observer.
+
+An Active Record Observer is an object that links itself to a model and register it's methods for callbacks. Your model's implementation remain clean, while you can reuse the code in the Observer to add behaviuor to more than one model class. Ok, you may say that we can also do that using callback classes, but it would still force us to add code to our model's implementation.
+
+Observer classes are subclasses of the +ActiveRecord::Observer+ class. When this class is subclassed, Active Record will look at the name of the new class and then strip the 'Observer' part to find the name of the Active Record class to observe.
+
+Consider a +Registration+ model, where we want to send an email everytime a new registration is created. Since sending emails is not directly related to our model's purpose, we could create an Observer to do just that:
+
+[source, ruby]
+------------------------------------------------------------------
+class RegistrationObserver < ActiveRecord::Observer
+ def after_create(model)
+ # code to send registration confirmation emails...
+ end
+end
+------------------------------------------------------------------
+
+Like in callback classes, the observer's methods receive the observed model as a parameter.
+
+Sometimes using the ModelName + Observer naming convention won't be the best choice, mainly when you want to use the same observer for more than one model class. It's possible to explicity specify the models that our observer should observe.
+
+[source, ruby]
+------------------------------------------------------------------
+class Auditor < ActiveRecord::Observer
+ observe User, Registration, Invoice
+end
+------------------------------------------------------------------
+
+=== Registering observers
+
+If you payed attention, you may be wondering where Active Record Observers are referenced in our applications, so they get instantiate and begin to interact with our models. For observers to work we need to register then in our application's *config/environment.rb* file. In this file there is a commented out line where we can define the observers that our application should load at start-up.
+
+[source, ruby]
+------------------------------------------------------------------
+# Activate observers that should always be running
+config.active_record.observers = :registration_observer, :auditor
+------------------------------------------------------------------
+
+=== Where to put the observers' source files
+
+By convention, you should always save your observers' source files inside *app/models*.
+
== Changelog
http://rails.lighthouseapp.com/projects/16213/tickets/26-active-record-validations-and-callbacks
Please sign in to comment.
Something went wrong with that request. Please try again.