Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > d51872cc0e1fdee944d71993f94ac764 > files > 248

ruby-activerecord-2.3.4-1mdv2010.0.noarch.rpm

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html 
     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>Module: ActiveRecord::Callbacks</title>
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  <meta http-equiv="Content-Script-Type" content="text/javascript" />
  <link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
  <script type="text/javascript">
  // <![CDATA[

  function popupCode( url ) {
    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
  }

  function toggleCode( id ) {
    if ( document.getElementById )
      elem = document.getElementById( id );
    else if ( document.all )
      elem = eval( "document.all." + id );
    else
      return false;

    elemStyle = elem.style;
    
    if ( elemStyle.display != "block" ) {
      elemStyle.display = "block"
    } else {
      elemStyle.display = "none"
    }

    return true;
  }
  
  // Make codeblocks hidden by default
  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
  
  // ]]>
  </script>

</head>
<body>



    <div id="classHeader">
        <table class="header-table">
        <tr class="top-aligned-row">
          <td><strong>Module</strong></td>
          <td class="class-name-in-header">ActiveRecord::Callbacks</td>
        </tr>
        <tr class="top-aligned-row">
            <td><strong>In:</strong></td>
            <td>
                <a href="../../files/lib/active_record/callbacks_rb.html">
                lib/active_record/callbacks.rb
                </a>
        <br />
            </td>
        </tr>

        </table>
    </div>
  <!-- banner header -->

  <div id="bodyContent">



  <div id="contextContent">

    <div id="description">
      <p>
<a href="Callbacks.html">Callbacks</a> are hooks into the lifecycle of an
Active Record object that allow you to trigger logic before or after an
alteration of the object state. This can be used to make sure that
associated and dependent objects are deleted when <tt>destroy</tt> is
called (by overwriting <tt><a
href="Callbacks.html#M000075">before_destroy</a></tt>) or to massage
attributes before they&#8216;re validated (by overwriting <tt><a
href="Callbacks.html#M000069">before_validation</a></tt>). As an example of
the callbacks initiated, consider the <tt><a
href="Base.html#M000524">Base#save</a></tt> call for a new record:
</p>
<ul>
<li>(-) <tt>save</tt>

</li>
<li>(-) <tt>valid</tt>

</li>
<li>(1) <tt><a href="Callbacks.html#M000069">before_validation</a></tt>

</li>
<li>(2) <tt><a
href="Callbacks.html#M000071">before_validation_on_create</a></tt>

</li>
<li>(-) <tt>validate</tt>

</li>
<li>(-) <tt>validate_on_create</tt>

</li>
<li>(3) <tt><a href="Callbacks.html#M000070">after_validation</a></tt>

</li>
<li>(4) <tt><a
href="Callbacks.html#M000072">after_validation_on_create</a></tt>

</li>
<li>(5) <tt><a href="Callbacks.html#M000063">before_save</a></tt>

</li>
<li>(6) <tt><a href="Callbacks.html#M000065">before_create</a></tt>

</li>
<li>(-) <tt>create</tt>

</li>
<li>(7) <tt><a href="Callbacks.html#M000066">after_create</a></tt>

</li>
<li>(8) <tt><a href="Callbacks.html#M000064">after_save</a></tt>

</li>
</ul>
<p>
That&#8216;s a total of eight callbacks, which gives you immense power to
react and prepare for each state in the Active Record lifecycle. The
sequence for calling <tt><a href="Base.html#M000524">Base#save</a></tt> an
existing record is similar, except that each <tt>_on_create</tt> callback
is replaced by the corresponding <tt>_on_update</tt> callback.
</p>
<p>
Examples:
</p>
<pre>
  class CreditCard &lt; ActiveRecord::Base
    # Strip everything but digits, so the user can specify &quot;555 234 34&quot; or
    # &quot;5552-3434&quot; or both will mean &quot;55523434&quot;
    def before_validation_on_create
      self.number = number.gsub(/[^0-9]/, &quot;&quot;) if attribute_present?(&quot;number&quot;)
    end
  end

  class Subscription &lt; ActiveRecord::Base
    before_create :record_signup

    private
      def record_signup
        self.signed_up_on = Date.today
      end
  end

  class Firm &lt; ActiveRecord::Base
    # Destroys the associated clients and people when the firm is destroyed
    before_destroy { |record| Person.destroy_all &quot;firm_id = #{record.id}&quot;   }
    before_destroy { |record| Client.destroy_all &quot;client_of = #{record.id}&quot; }
  end
</pre>
<h2>Inheritable callback queues</h2>
<p>
Besides the overwritable callback methods, it&#8216;s also possible to
register callbacks through the use of the callback macros. Their main
advantage is that the macros add behavior into a callback queue that is
kept intact down through an inheritance hierarchy. Example:
</p>
<pre>
  class Topic &lt; ActiveRecord::Base
    before_destroy :destroy_author
  end

  class Reply &lt; Topic
    before_destroy :destroy_readers
  end
</pre>
<p>
Now, when <tt>Topic#destroy</tt> is run only <tt>destroy_author</tt> is
called. When <tt>Reply#destroy</tt> is run, both <tt>destroy_author</tt>
and <tt>destroy_readers</tt> are called. Contrast this to the situation
where we&#8216;ve implemented the save behavior through overwriteable
methods:
</p>
<pre>
  class Topic &lt; ActiveRecord::Base
    def before_destroy() destroy_author end
  end

  class Reply &lt; Topic
    def before_destroy() destroy_readers end
  end
</pre>
<p>
In that case, <tt>Reply#destroy</tt> would only run
<tt>destroy_readers</tt> and <em>not</em> <tt>destroy_author</tt>. So, use
the callback macros when you want to ensure that a certain callback is
called for the entire hierarchy, and use the regular overwriteable methods
when you want to leave it up to each descendant to decide whether they want
to call <tt>super</tt> and trigger the inherited callbacks.
</p>
<p>
*IMPORTANT:* In order for inheritance to work for the callback queues, you
must specify the callbacks before specifying the associations. Otherwise,
you might trigger the loading of a child before the parent has registered
the callbacks and they won&#8216;t be inherited.
</p>
<h2>Types of callbacks</h2>
<p>
There are four types of callbacks accepted by the callback macros: Method
references (symbol), callback objects, inline methods (using a proc), and
inline eval methods (using a string). Method references and callback
objects are the recommended approaches, inline methods using a proc are
sometimes appropriate (such as for creating mix-ins), and inline eval
methods are deprecated.
</p>
<p>
The method reference callbacks work by specifying a protected or private
method available in the object, like this:
</p>
<pre>
  class Topic &lt; ActiveRecord::Base
    before_destroy :delete_parents

    private
      def delete_parents
        self.class.delete_all &quot;parent_id = #{id}&quot;
      end
  end
</pre>
<p>
The callback objects have methods named after the callback called with the
record as the only parameter, such as:
</p>
<pre>
  class BankAccount &lt; ActiveRecord::Base
    before_save      EncryptionWrapper.new
    after_save       EncryptionWrapper.new
    after_initialize EncryptionWrapper.new
  end

  class EncryptionWrapper
    def before_save(record)
      record.credit_card_number = encrypt(record.credit_card_number)
    end

    def after_save(record)
      record.credit_card_number = decrypt(record.credit_card_number)
    end

    alias_method :after_find, :after_save

    private
      def encrypt(value)
        # Secrecy is committed
      end

      def decrypt(value)
        # Secrecy is unveiled
      end
  end
</pre>
<p>
So you specify the object you want messaged on a given callback. When that
callback is triggered, the object has a method by the name of the callback
messaged. You can make these callbacks more flexible by passing in other
initialization data such as the name of the attribute to work with:
</p>
<pre>
  class BankAccount &lt; ActiveRecord::Base
    before_save      EncryptionWrapper.new(&quot;credit_card_number&quot;)
    after_save       EncryptionWrapper.new(&quot;credit_card_number&quot;)
    after_initialize EncryptionWrapper.new(&quot;credit_card_number&quot;)
  end

  class EncryptionWrapper
    def initialize(attribute)
      @attribute = attribute
    end

    def before_save(record)
      record.send(&quot;#{@attribute}=&quot;, encrypt(record.send(&quot;#{@attribute}&quot;)))
    end

    def after_save(record)
      record.send(&quot;#{@attribute}=&quot;, decrypt(record.send(&quot;#{@attribute}&quot;)))
    end

    alias_method :after_find, :after_save

    private
      def encrypt(value)
        # Secrecy is committed
      end

      def decrypt(value)
        # Secrecy is unveiled
      end
  end
</pre>
<p>
The callback macros usually accept a symbol for the method they&#8216;re
supposed to run, but you can also pass a &quot;method string&quot;, which
will then be evaluated within the binding of the callback. Example:
</p>
<pre>
  class Topic &lt; ActiveRecord::Base
    before_destroy 'self.class.delete_all &quot;parent_id = #{id}&quot;'
  end
</pre>
<p>
Notice that single quotes (&#8217;) are used so the <tt>#{id}</tt> part
isn&#8216;t evaluated until the callback is triggered. Also note that these
inline callbacks can be stacked just like the regular ones:
</p>
<pre>
  class Topic &lt; ActiveRecord::Base
    before_destroy 'self.class.delete_all &quot;parent_id = #{id}&quot;',
                   'puts &quot;Evaluated after parents are destroyed&quot;'
  end
</pre>
<h2>The <tt>after_find</tt> and <tt>after_initialize</tt> exceptions</h2>
<p>
Because <tt>after_find</tt> and <tt>after_initialize</tt> are called for
each object found and instantiated by a finder, such as <tt><a
href="Base.html#M000458">Base.find</a>(:all)</tt>, we&#8216;ve had to
implement a simple performance constraint (50% more speed on a simple test
case). Unlike all the other callbacks, <tt>after_find</tt> and
<tt>after_initialize</tt> will only be run if an explicit implementation is
defined (<tt>def after_find</tt>). In that case, all of the callback types
will be called.
</p>
<h2><tt><a href="Callbacks.html#M000069">before_validation</a>*</tt> returning statements</h2>
<p>
If the returning value of a <tt><a
href="Callbacks.html#M000069">before_validation</a></tt> callback can be
evaluated to <tt>false</tt>, the process will be aborted and <tt><a
href="Base.html#M000524">Base#save</a></tt> will return <tt>false</tt>. If
<a href="Base.html#M000524">Base#save</a>! is called it will raise a <a
href="RecordInvalid.html">ActiveRecord::RecordInvalid</a> exception.
Nothing will be appended to the errors object.
</p>
<h2>Canceling callbacks</h2>
<p>
If a <tt>before_*</tt> callback returns <tt>false</tt>, all the later
callbacks and the associated action are cancelled. If an <tt>after_*</tt>
callback returns <tt>false</tt>, all the later callbacks are cancelled. <a
href="Callbacks.html">Callbacks</a> are generally run in the order they are
defined, with the exception of callbacks defined as methods on the model,
which are called last.
</p>
<h2><a href="Transactions.html">Transactions</a></h2>
<p>
The entire callback chain of a <tt>save</tt>, <tt>save!</tt>, or
<tt>destroy</tt> call runs within a transaction. That includes
<tt>after_*</tt> hooks. If everything goes fine a COMMIT is executed once
the chain has been completed.
</p>
<p>
If a <tt>before_*</tt> callback cancels the action a ROLLBACK is issued.
You can also trigger a ROLLBACK raising an exception in any of the
callbacks, including <tt>after_*</tt> hooks. Note, however, that in that
case the client needs to be aware of it because an ordinary <tt>save</tt>
will raise such exception instead of quietly returning <tt>false</tt>.
</p>

    </div>


   </div>

    <div id="method-list">
      <h3 class="section-bar">Methods</h3>

      <div class="name-list">
      <a href="#M000066">after_create</a>&nbsp;&nbsp;
      <a href="#M000076">after_destroy</a>&nbsp;&nbsp;
      <a href="#M000064">after_save</a>&nbsp;&nbsp;
      <a href="#M000068">after_update</a>&nbsp;&nbsp;
      <a href="#M000070">after_validation</a>&nbsp;&nbsp;
      <a href="#M000072">after_validation_on_create</a>&nbsp;&nbsp;
      <a href="#M000074">after_validation_on_update</a>&nbsp;&nbsp;
      <a href="#M000065">before_create</a>&nbsp;&nbsp;
      <a href="#M000075">before_destroy</a>&nbsp;&nbsp;
      <a href="#M000063">before_save</a>&nbsp;&nbsp;
      <a href="#M000067">before_update</a>&nbsp;&nbsp;
      <a href="#M000069">before_validation</a>&nbsp;&nbsp;
      <a href="#M000071">before_validation_on_create</a>&nbsp;&nbsp;
      <a href="#M000073">before_validation_on_update</a>&nbsp;&nbsp;
      </div>
    </div>

  </div>


    <!-- if includes -->

    <div id="section">


    <div id="constants-list">
      <h3 class="section-bar">Constants</h3>

      <div class="name-list">
        <table summary="Constants">
        <tr class="top-aligned-row context-row">
          <td class="context-item-name">CALLBACKS</td>
          <td>=</td>
          <td class="context-item-value">%w(       after_find after_initialize before_save after_save before_create after_create before_update after_update before_validation       after_validation before_validation_on_create after_validation_on_create before_validation_on_update       after_validation_on_update before_destroy after_destroy     )</td>
        </tr>
        </table>
      </div>
    </div>



      


    <!-- if method_list -->
    <div id="methods">
      <h3 class="section-bar">Public Instance methods</h3>

      <div id="method-M000066" class="method-detail">
        <a name="M000066"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000066.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000066.html');return false;">
          <span class="method-name">after_create</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>after</em> <tt><a href="Base.html#M000524">Base.save</a></tt>
on new objects that haven&#8216;t been saved yet (no record exists). Note
that this callback is still wrapped in the transaction around
<tt>save</tt>. For example, if you invoke an external indexer at this point
it won&#8216;t see the changes in the database.
</p>
        </div>
      </div>

      <div id="method-M000076" class="method-detail">
        <a name="M000076"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000076.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000076.html');return false;">
          <span class="method-name">after_destroy</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>after</em> <tt><a
href="Base.html#M000467">Base.destroy</a></tt> (and all the attributes have
been frozen).
</p>
<pre>
 class Contact &lt; ActiveRecord::Base
   after_destroy { |record| logger.info( &quot;Contact #{record.id} was destroyed.&quot; ) }
 end
</pre>
        </div>
      </div>

      <div id="method-M000064" class="method-detail">
        <a name="M000064"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000064.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000064.html');return false;">
          <span class="method-name">after_save</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>after</em> <tt><a href="Base.html#M000524">Base.save</a></tt>
(regardless of whether it&#8216;s a <tt>create</tt> or <tt>update</tt>
save). Note that this callback is still wrapped in the transaction around
<tt>save</tt>. For example, if you invoke an external indexer at this point
it won&#8216;t see the changes in the database.
</p>
<pre>
 class Contact &lt; ActiveRecord::Base
   after_save { logger.info( 'New contact saved!' ) }
 end
</pre>
        </div>
      </div>

      <div id="method-M000068" class="method-detail">
        <a name="M000068"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000068.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000068.html');return false;">
          <span class="method-name">after_update</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>after</em> <tt><a href="Base.html#M000524">Base.save</a></tt>
on existing objects that have a record. Note that this callback is still
wrapped in the transaction around <tt>save</tt>. For example, if you invoke
an external indexer at this point it won&#8216;t see the changes in the
database.
</p>
        </div>
      </div>

      <div id="method-M000070" class="method-detail">
        <a name="M000070"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000070.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000070.html');return false;">
          <span class="method-name">after_validation</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>after</em> <tt><a
href="Validations.html#M000098">Validations.validate</a></tt> (which is
part of the <tt><a href="Base.html#M000524">Base.save</a></tt> call).
</p>
        </div>
      </div>

      <div id="method-M000072" class="method-detail">
        <a name="M000072"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000072.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000072.html');return false;">
          <span class="method-name">after_validation_on_create</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>after</em> <tt><a
href="Validations.html#M000098">Validations.validate</a></tt> (which is
part of the <tt><a href="Base.html#M000524">Base.save</a></tt> call) on new
objects that haven&#8216;t been saved yet (no record exists).
</p>
        </div>
      </div>

      <div id="method-M000074" class="method-detail">
        <a name="M000074"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000074.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000074.html');return false;">
          <span class="method-name">after_validation_on_update</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>after</em> <tt><a
href="Validations.html#M000098">Validations.validate</a></tt> (which is
part of the <tt><a href="Base.html#M000524">Base.save</a></tt> call) on
existing objects that have a record.
</p>
        </div>
      </div>

      <div id="method-M000065" class="method-detail">
        <a name="M000065"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000065.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000065.html');return false;">
          <span class="method-name">before_create</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>before</em> <tt><a
href="Base.html#M000524">Base.save</a></tt> on new objects that
haven&#8216;t been saved yet (no record exists).
</p>
        </div>
      </div>

      <div id="method-M000075" class="method-detail">
        <a name="M000075"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000075.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000075.html');return false;">
          <span class="method-name">before_destroy</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>before</em> <tt><a
href="Base.html#M000467">Base.destroy</a></tt>.
</p>
<p>
Note: If you need to <em>destroy</em> or <em>nullify</em> associated
records first, use the <tt>:dependent</tt> option on your associations.
</p>
        </div>
      </div>

      <div id="method-M000063" class="method-detail">
        <a name="M000063"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000063.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000063.html');return false;">
          <span class="method-name">before_save</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>before</em> <tt><a
href="Base.html#M000524">Base.save</a></tt> (regardless of whether
it&#8216;s a <tt>create</tt> or <tt>update</tt> save).
</p>
        </div>
      </div>

      <div id="method-M000067" class="method-detail">
        <a name="M000067"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000067.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000067.html');return false;">
          <span class="method-name">before_update</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>before</em> <tt><a
href="Base.html#M000524">Base.save</a></tt> on existing objects that have a
record.
</p>
        </div>
      </div>

      <div id="method-M000069" class="method-detail">
        <a name="M000069"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000069.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000069.html');return false;">
          <span class="method-name">before_validation</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>before</em> <tt><a
href="Validations.html#M000098">Validations.validate</a></tt> (which is
part of the <tt><a href="Base.html#M000524">Base.save</a></tt> call).
</p>
        </div>
      </div>

      <div id="method-M000071" class="method-detail">
        <a name="M000071"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000071.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000071.html');return false;">
          <span class="method-name">before_validation_on_create</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>before</em> <tt><a
href="Validations.html#M000098">Validations.validate</a></tt> (which is
part of the <tt><a href="Base.html#M000524">Base.save</a></tt> call) on new
objects that haven&#8216;t been saved yet (no record exists).
</p>
        </div>
      </div>

      <div id="method-M000073" class="method-detail">
        <a name="M000073"></a>

        <div class="method-heading">
          <a href="Callbacks.src/M000073.html" target="Code" class="method-signature"
            onclick="popupCode('Callbacks.src/M000073.html');return false;">
          <span class="method-name">before_validation_on_update</span><span class="method-args">()</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
Is called <em>before</em> <tt><a
href="Validations.html#M000098">Validations.validate</a></tt> (which is
part of the <tt><a href="Base.html#M000524">Base.save</a></tt> call) on
existing objects that have a record.
</p>
        </div>
      </div>


    </div>


  </div>


<div id="validator-badges">
  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
</div>

</body>
</html>