Regenerate Guides HTML

This commit is contained in:
Mike Gunderloy
2008-12-27 16:15:52 -06:00
parent 8b1d69d197
commit fa6218c923
21 changed files with 4572 additions and 4530 deletions

View File

@@ -292,16 +292,16 @@ ul#navMain {
<h1>Ruby on Rails 2.2 Release Notes</h1>
<div id="preamble">
<div class="sectionbody">
<div class="para"><p>Rails 2.2 delivers a number of new and improved features. This list covers the major upgrades, but doesn't include every little bug fix and change. If you want to see everything, check out the <a href="http://github.com/rails/rails/commits/master">list of commits</a> in the main Rails repository on GitHub.</p></div>
<div class="para"><p>Along with Rails, 2.2 marks the launch of the <a href="http://guides.rubyonrails.org/">Ruby on Rails Guides</a>, the first results of the ongoing <a href="http://hackfest.rubyonrails.org/guide">Rails Guides hackfest</a>. This site will deliver high-quality documentation of the major features of Rails.</p></div>
<div class="paragraph"><p>Rails 2.2 delivers a number of new and improved features. This list covers the major upgrades, but doesn&#8217;t include every little bug fix and change. If you want to see everything, check out the <a href="http://github.com/rails/rails/commits/master">list of commits</a> in the main Rails repository on GitHub.</p></div>
<div class="paragraph"><p>Along with Rails, 2.2 marks the launch of the <a href="http://guides.rubyonrails.org/">Ruby on Rails Guides</a>, the first results of the ongoing <a href="http://hackfest.rubyonrails.org/guide">Rails Guides hackfest</a>. This site will deliver high-quality documentation of the major features of Rails.</p></div>
</div>
</div>
<h2 id="_infrastructure">1. Infrastructure</h2>
<div class="sectionbody">
<div class="para"><p>Rails 2.2 is a significant release for the infrastructure that keeps Rails humming along and connected to the rest of the world.</p></div>
<div class="paragraph"><p>Rails 2.2 is a significant release for the infrastructure that keeps Rails humming along and connected to the rest of the world.</p></div>
<h3 id="_internationalization">1.1. Internationalization</h3>
<div class="para"><p>Rails 2.2 supplies an easy system for internationalization (or i18n, for those of you tired of typing).</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>Rails 2.2 supplies an easy system for internationalization (or i18n, for those of you tired of typing).</p></div>
<div class="ulist"><ul>
<li>
<p>
Lead Contributors: Rails i18 Team
@@ -311,7 +311,7 @@ Lead Contributors: Rails i18 Team
<p>
More information :
</p>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<a href="http://rails-i18n.org">Official Rails i18 website</a>
@@ -331,12 +331,12 @@ More information :
</li>
</ul></div>
<h3 id="_compatibility_with_ruby_1_9_and_jruby">1.2. Compatibility with Ruby 1.9 and JRuby</h3>
<div class="para"><p>Along with thread safety, a lot of work has been done to make Rails work well with JRuby and the upcoming Ruby 1.9. With Ruby 1.9 being a moving target, running edge Rails on edge Ruby is still a hit-or-miss proposition, but Rails is ready to make the transition to Ruby 1.9 when the latter is released.</p></div>
<div class="paragraph"><p>Along with thread safety, a lot of work has been done to make Rails work well with JRuby and the upcoming Ruby 1.9. With Ruby 1.9 being a moving target, running edge Rails on edge Ruby is still a hit-or-miss proposition, but Rails is ready to make the transition to Ruby 1.9 when the latter is released.</p></div>
</div>
<h2 id="_documentation">2. Documentation</h2>
<div class="sectionbody">
<div class="para"><p>The internal documentation of Rails, in the form of code comments, has been improved in numerous places. In addition, the <a href="http://guides.rubyonrails.org/">Ruby on Rails Guides</a> project is the definitive source for information on major Rails components. In its first official release, the Guides page includes:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>The internal documentation of Rails, in the form of code comments, has been improved in numerous places. In addition, the <a href="http://guides.rubyonrails.org/">Ruby on Rails Guides</a> project is the definitive source for information on major Rails components. In its first official release, the Guides page includes:</p></div>
<div class="ulist"><ul>
<li>
<p>
<a href="http://guides.rubyonrails.org/getting_started_with_rails.html">Getting Started with Rails</a>
@@ -408,17 +408,16 @@ More information :
</p>
</li>
</ul></div>
<div class="para"><p>All told, the Guides provide tens of thousands of words of guidance for beginning and intermediate Rails developers.</p></div>
<div class="para"><p>If you want to generate these guides locally, inside your application:</p></div>
<div class="paragraph"><p>All told, the Guides provide tens of thousands of words of guidance for beginning and intermediate Rails developers.</p></div>
<div class="paragraph"><p>If you want to generate these guides locally, inside your application:</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>rake doc<span style="color: #990000">:</span>guides
</tt></pre></div></div>
<div class="para"><p>This will put the guides inside <tt>RAILS_ROOT/doc/guides</tt> and you may start surfing straight away by opening <tt>RAILS_ROOT/doc/guides/index.html</tt> in your favourite browser.</p></div>
<div class="ilist"><ul>
<pre><tt>rake doc<span style="color: #990000">:</span>guides</tt></pre></div></div>
<div class="paragraph"><p>This will put the guides inside <tt>RAILS_ROOT/doc/guides</tt> and you may start surfing straight away by opening <tt>RAILS_ROOT/doc/guides/index.html</tt> in your favourite browser.</p></div>
<div class="ulist"><ul>
<li>
<p>
Lead Contributors: <a href="http://guides.rails.info/authors.html">Rails Documentation Team</a>
@@ -433,7 +432,7 @@ Major contributions from <a href="http://advogato.org/person/fxn/diary.html">Xav
<p>
More information:
</p>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<a href="http://hackfest.rubyonrails.org/guide">Rails Guides hackfest</a>
@@ -450,7 +449,7 @@ More information:
</div>
<h2 id="_better_integration_with_http_out_of_the_box_etag_support">3. Better integration with HTTP : Out of the box ETag support</h2>
<div class="sectionbody">
<div class="para"><p>Supporting the etag and last modified timestamp in HTTP headers means that Rails can now send back an empty response if it gets a request for a resource that hasn't been modified lately. This allows you to check whether a response needs to be sent at all.</p></div>
<div class="paragraph"><p>Supporting the etag and last modified timestamp in HTTP headers means that Rails can now send back an empty response if it gets a request for a resource that hasn&#8217;t been modified lately. This allows you to check whether a response needs to be sent at all.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -484,26 +483,24 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-style: italic"><span style="color: #9A1900"># instead of rendering the template.</span></span>
fresh_when<span style="color: #990000">(:</span>last_modified <span style="color: #990000">=&gt;</span> <span style="color: #009900">@article</span><span style="color: #990000">.</span>published_at<span style="color: #990000">.</span>utc<span style="color: #990000">,</span> <span style="color: #990000">:</span>etag <span style="color: #990000">=&gt;</span> <span style="color: #009900">@article</span><span style="color: #990000">)</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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
</div>
<h2 id="_thread_safety">4. Thread Safety</h2>
<div class="sectionbody">
<div class="para"><p>The work done to make Rails thread-safe is rolling out in Rails 2.2. Depending on your web server infrastructure, this means you can handle more requests with fewer copies of Rails in memory, leading to better server performance and higher utilization of multiple cores.</p></div>
<div class="para"><p>To enable multithreaded dispatching in production mode of your application, add the following line in your <tt>config/environments/production.rb</tt>:</p></div>
<div class="paragraph"><p>The work done to make Rails thread-safe is rolling out in Rails 2.2. Depending on your web server infrastructure, this means you can handle more requests with fewer copies of Rails in memory, leading to better server performance and higher utilization of multiple cores.</p></div>
<div class="paragraph"><p>To enable multithreaded dispatching in production mode of your application, add the following line in your <tt>config/environments/production.rb</tt>:</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>config<span style="color: #990000">.</span>threadsafe!
</tt></pre></div></div>
<div class="ilist"><ul>
<pre><tt>config<span style="color: #990000">.</span>threadsafe!</tt></pre></div></div>
<div class="ulist"><ul>
<li>
<p>
More information :
</p>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<a href="http://m.onkey.org/2008/10/23/thread-safety-for-your-rails">Thread safety for your Rails</a>
@@ -525,10 +522,10 @@ More information :
</div>
<h2 id="_active_record">5. Active Record</h2>
<div class="sectionbody">
<div class="para"><p>There are two big additions to talk about here: transactional migrations and pooled database transactions. There's also a new (and cleaner) syntax for join table conditions, as well as a number of smaller improvements.</p></div>
<div class="paragraph"><p>There are two big additions to talk about here: transactional migrations and pooled database transactions. There&#8217;s also a new (and cleaner) syntax for join table conditions, as well as a number of smaller improvements.</p></div>
<h3 id="_transactional_migrations">5.1. Transactional Migrations</h3>
<div class="para"><p>Historically, multiple-step Rails migrations have been a source of trouble. If something went wrong during a migration, everything before the error changed the database and everything after the error wasn't applied. Also, the migration version was stored as having been executed, which means that it couldn't be simply rerun by <tt>rake db:migrate:redo</tt> after you fix the problem. Transactional migrations change this by wrapping migration steps in a DDL transaction, so that if any of them fail, the entire migration is undone. In Rails 2.2, transactional migrations are supported on PostgreSQL out of the box. The code is extensible to other database types in the future - and IBM has already extended it to support the DB2 adapter.</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>Historically, multiple-step Rails migrations have been a source of trouble. If something went wrong during a migration, everything before the error changed the database and everything after the error wasn&#8217;t applied. Also, the migration version was stored as having been executed, which means that it couldn&#8217;t be simply rerun by <tt>rake db:migrate:redo</tt> after you fix the problem. Transactional migrations change this by wrapping migration steps in a DDL transaction, so that if any of them fail, the entire migration is undone. In Rails 2.2, transactional migrations are supported on PostgreSQL out of the box. The code is extensible to other database types in the future - and IBM has already extended it to support the DB2 adapter.</p></div>
<div class="ulist"><ul>
<li>
<p>
Lead Contributor: <a href="http://adam.blog.heroku.com/">Adam Wiggins</a>
@@ -538,7 +535,7 @@ Lead Contributor: <a href="http://adam.blog.heroku.com/">Adam Wiggins</a>
<p>
More information:
</p>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<a href="http://adam.blog.heroku.com/past/2008/9/3/ddl_transactions/">DDL Transactions</a>
@@ -553,7 +550,7 @@ More information:
</li>
</ul></div>
<h3 id="_connection_pooling">5.2. Connection Pooling</h3>
<div class="para"><p>Connection pooling lets Rails distribute database requests across a pool of database connections that will grow to a maximum size (by default 5, but you can add a <tt>pool</tt> key to your <tt>database.yml</tt> to adjust this). This helps remove bottlenecks in applications that support many concurrent users. There's also a <tt>wait_timeout</tt> that defaults to 5 seconds before giving up. <tt>ActiveRecord::Base.connection_pool</tt> gives you direct access to the pool if you need it.</p></div>
<div class="paragraph"><p>Connection pooling lets Rails distribute database requests across a pool of database connections that will grow to a maximum size (by default 5, but you can add a <tt>pool</tt> key to your <tt>database.yml</tt> to adjust this). This helps remove bottlenecks in applications that support many concurrent users. There&#8217;s also a <tt>wait_timeout</tt> that defaults to 5 seconds before giving up. <tt>ActiveRecord::Base.connection_pool</tt> gives you direct access to the pool if you need it.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -564,9 +561,8 @@ http://www.gnu.org/software/src-highlite -->
username<span style="color: #990000">:</span> root
database<span style="color: #990000">:</span> sample_development
pool<span style="color: #990000">:</span> <span style="color: #993399">10</span>
wait_timeout<span style="color: #990000">:</span> <span style="color: #993399">10</span>
</tt></pre></div></div>
<div class="ilist"><ul>
wait_timeout<span style="color: #990000">:</span> <span style="color: #993399">10</span></tt></pre></div></div>
<div class="ulist"><ul>
<li>
<p>
Lead Contributor: <a href="http://blog.nicksieger.com/">Nick Sieger</a>
@@ -576,17 +572,17 @@ Lead Contributor: <a href="http://blog.nicksieger.com/">Nick Sieger</a>
<p>
More information:
</p>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<a href="http://ryandaigle.com/articles/2008/9/7/what-s-new-in-edge-rails-connection-pools">What's New in Edge Rails: Connection Pools</a>
<a href="http://ryandaigle.com/articles/2008/9/7/what-s-new-in-edge-rails-connection-pools">What&#8217;s New in Edge Rails: Connection Pools</a>
</p>
</li>
</ul></div>
</li>
</ul></div>
<h3 id="_hashes_for_join_table_conditions">5.3. Hashes for Join Table Conditions</h3>
<div class="para"><p>You can now specify conditions on join tables using a hash. This is a big help if you need to query across complex joins.</p></div>
<div class="paragraph"><p>You can now specify conditions on join tables using a hash. This is a big help if you need to query across complex joins.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -601,35 +597,33 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
<span style="font-style: italic"><span style="color: #9A1900"># Get all products with copyright-free photos:</span></span>
Product<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>joins <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>photos <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>copyright <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span> <span style="color: #FF0000">}}</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="ilist"><ul>
Product<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>joins <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>photos <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>copyright <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span> <span style="color: #FF0000">}}</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="ulist"><ul>
<li>
<p>
More information:
</p>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<a href="http://ryandaigle.com/articles/2008/7/7/what-s-new-in-edge-rails-easy-join-table-conditions">What's New in Edge Rails: Easy Join Table Conditions</a>
<a href="http://ryandaigle.com/articles/2008/7/7/what-s-new-in-edge-rails-easy-join-table-conditions">What&#8217;s New in Edge Rails: Easy Join Table Conditions</a>
</p>
</li>
</ul></div>
</li>
</ul></div>
<h3 id="_new_dynamic_finders">5.4. New Dynamic Finders</h3>
<div class="para"><p>Two new sets of methods have been added to Active Record's dynamic finders family.</p></div>
<div class="paragraph"><p>Two new sets of methods have been added to Active Record&#8217;s dynamic finders family.</p></div>
<h4 id="_tt_find_last_by_lt_attribute_gt_tt">5.4.1. <tt>find_last_by_&lt;attribute&gt;</tt></h4>
<div class="para"><p>The <tt>find_last_by_&lt;attribute&gt;</tt> method is equivalent to <tt>Model.last(:conditions &#8658; {:attribute &#8658; value})</tt></p></div>
<div class="paragraph"><p>The <tt>find_last_by_&lt;attribute&gt;</tt> method is equivalent to <tt>Model.last(:conditions =&gt; {:attribute =&gt; value})</tt></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"># Get the last user who signed up from London</span></span>
User<span style="color: #990000">.</span>find_last_by_city<span style="color: #990000">(</span><span style="color: #FF0000">'London'</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="ilist"><ul>
User<span style="color: #990000">.</span>find_last_by_city<span style="color: #990000">(</span><span style="color: #FF0000">'London'</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="ulist"><ul>
<li>
<p>
Lead Contributor: <a href="http://www.workingwithrails.com/person/9147-emilio-tagua">Emilio Tagua</a>
@@ -637,16 +631,15 @@ Lead Contributor: <a href="http://www.workingwithrails.com/person/9147-emilio-ta
</li>
</ul></div>
<h4 id="_tt_find_by_lt_attribute_gt_tt">5.4.2. <tt>find_by_&lt;attribute&gt;!</tt></h4>
<div class="para"><p>The new bang! version of <tt>find_by_&lt;attribute&gt;!</tt> is equivalent to <tt>Model.first(:conditions &#8658; {:attribute &#8658; value}) || raise ActiveRecord::RecordNotFound</tt> Instead of returning <tt>nil</tt> if it can't find a matching record, this method will raise an exception if it cannot find a match.</p></div>
<div class="paragraph"><p>The new bang! version of <tt>find_by_&lt;attribute&gt;!</tt> is equivalent to <tt>Model.first(:conditions =&gt; {:attribute =&gt; value}) || raise ActiveRecord::RecordNotFound</tt> Instead of returning <tt>nil</tt> if it can&#8217;t find a matching record, this method will raise an exception if it cannot find a match.</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"># Raise ActiveRecord::RecordNotFound exception if 'Moby' hasn't signed up yet!</span></span>
User<span style="color: #990000">.</span>find_by_name!<span style="color: #990000">(</span><span style="color: #FF0000">'Moby'</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="ilist"><ul>
User<span style="color: #990000">.</span>find_by_name!<span style="color: #990000">(</span><span style="color: #FF0000">'Moby'</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="ulist"><ul>
<li>
<p>
Lead Contributor: <a href="http://blog.hasmanythrough.com">Josh Susser</a>
@@ -654,8 +647,8 @@ Lead Contributor: <a href="http://blog.hasmanythrough.com">Josh Susser</a>
</li>
</ul></div>
<h3 id="_associations_respect_private_protected_scope">5.5. Associations Respect Private/Protected Scope</h3>
<div class="para"><p>Active Record association proxies now respect the scope of methods on the proxied object. Previously (given User has_one :account) <tt>@user.account.private_method</tt> would call the private method on the associated Account object. That fails in Rails 2.2; if you need this functionality, you should use <tt>@user.account.send(:private_method)</tt> (or make the method public instead of private or protected). Please note that if you're overriding <tt>method_missing</tt>, you should also override <tt>respond_to</tt> to match the behavior in order for associations to function normally.</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>Active Record association proxies now respect the scope of methods on the proxied object. Previously (given User has_one :account) <tt>@user.account.private_method</tt> would call the private method on the associated Account object. That fails in Rails 2.2; if you need this functionality, you should use <tt>@user.account.send(:private_method)</tt> (or make the method public instead of private or protected). Please note that if you&#8217;re overriding <tt>method_missing</tt>, you should also override <tt>respond_to</tt> to match the behavior in order for associations to function normally.</p></div>
<div class="ulist"><ul>
<li>
<p>
Lead Contributor: Adam Milligan
@@ -665,7 +658,7 @@ Lead Contributor: Adam Milligan
<p>
More information:
</p>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<a href="http://afreshcup.com/2008/10/24/rails-22-change-private-methods-on-association-proxies-are-private/">Rails 2.2 Change: Private Methods on Association Proxies are Private</a>
@@ -675,7 +668,7 @@ More information:
</li>
</ul></div>
<h3 id="_other_activerecord_changes">5.6. Other ActiveRecord Changes</h3>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<tt>rake db:migrate:redo</tt> now accepts an optional VERSION to target that specific migration to redo
@@ -688,7 +681,7 @@ Set <tt>config.active_record.timestamped_migrations = false</tt> to have migrati
</li>
<li>
<p>
Counter cache columns (for associations declared with <tt>:counter_cache &#8658; true</tt>) do not need to be initialized to zero any longer.
Counter cache columns (for associations declared with <tt>:counter_cache =&gt; true</tt>) do not need to be initialized to zero any longer.
</p>
</li>
<li>
@@ -700,9 +693,9 @@ Counter cache columns (for associations declared with <tt>:counter_cache &#8658;
</div>
<h2 id="_action_controller">6. Action Controller</h2>
<div class="sectionbody">
<div class="para"><p>On the controller side, there are several changes that will help tidy up your routes. There are also some internal changes in the routing engine to lower memory usage on complex applications.</p></div>
<div class="paragraph"><p>On the controller side, there are several changes that will help tidy up your routes. There are also some internal changes in the routing engine to lower memory usage on complex applications.</p></div>
<h3 id="_shallow_route_nesting">6.1. Shallow Route Nesting</h3>
<div class="para"><p>Shallow route nesting provides a solution to the well-known difficulty of using deeply-nested resources. With shallow nesting, you need only supply enough information to uniquely identify the resource that you want to work with.</p></div>
<div class="paragraph"><p>Shallow route nesting provides a solution to the well-known difficulty of using deeply-nested resources. With shallow nesting, you need only supply enough information to uniquely identify the resource that you want to work with.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -712,9 +705,8 @@ http://www.gnu.org/software/src-highlite -->
publisher<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>magazines <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>magazine<span style="color: #990000">|</span>
magazine<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos
<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>This will enable recognition of (among others) these routes:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This will enable recognition of (among others) these routes:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>/publishers/1 ==&gt; publisher_path(1)
@@ -723,7 +715,7 @@ http://www.gnu.org/software/src-highlite -->
/magazines/2/photos ==&gt; magazines_photos_path(2)
/photos/3 ==&gt; photo_path(3)</tt></pre>
</div></div>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
Lead Contributor: <a href="http://www.unwwwired.net/">S. Brent Faulkner</a>
@@ -733,7 +725,7 @@ Lead Contributor: <a href="http://www.unwwwired.net/">S. Brent Faulkner</a>
<p>
More information:
</p>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<a href="http://guides.rails.info/routing/routing_outside_in.html#_nested_resources">Rails Routing from the Outside In</a>
@@ -741,22 +733,21 @@ More information:
</li>
<li>
<p>
<a href="http://ryandaigle.com/articles/2008/9/7/what-s-new-in-edge-rails-shallow-routes">What's New in Edge Rails: Shallow Routes</a>
<a href="http://ryandaigle.com/articles/2008/9/7/what-s-new-in-edge-rails-shallow-routes">What&#8217;s New in Edge Rails: Shallow Routes</a>
</p>
</li>
</ul></div>
</li>
</ul></div>
<h3 id="_method_arrays_for_member_or_collection_routes">6.2. Method Arrays for Member or Collection Routes</h3>
<div class="para"><p>You can now supply an array of methods for new member or collection routes. This removes the annoyance of having to define a route as accepting any verb as soon as you need it to handle more than one. With Rails 2.2, this is a legitimate route declaration:</p></div>
<div class="paragraph"><p>You can now supply an array of methods for new member or collection routes. This removes the annoyance of having to define a route as accepting any verb as soon as you need it to handle more than one. With Rails 2.2, this is a legitimate route declaration:</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>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>collection <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>search <span style="color: #990000">=&gt;</span> <span style="color: #990000">[:</span>get<span style="color: #990000">,</span> <span style="color: #990000">:</span>post<span style="color: #990000">]</span> <span style="color: #FF0000">}</span>
</tt></pre></div></div>
<div class="ilist"><ul>
<pre><tt>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>collection <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>search <span style="color: #990000">=&gt;</span> <span style="color: #990000">[:</span>get<span style="color: #990000">,</span> <span style="color: #990000">:</span>post<span style="color: #990000">]</span> <span style="color: #FF0000">}</span></tt></pre></div></div>
<div class="ulist"><ul>
<li>
<p>
Lead Contributor: <a href="http://brennandunn.com/">Brennan Dunn</a>
@@ -764,16 +755,15 @@ Lead Contributor: <a href="http://brennandunn.com/">Brennan Dunn</a>
</li>
</ul></div>
<h3 id="_resources_with_specific_actions">6.3. Resources With Specific Actions</h3>
<div class="para"><p>By default, when you use <tt>map.resources</tt> to create a route, Rails generates routes for seven default actions (index, show, create, new, edit, update, and destroy). But each of these routes takes up memory in your application, and causes Rails to generate additional routing logic. Now you can use the <tt>:only</tt> and <tt>:except</tt> options to fine-tune the routes that Rails will generate for resources. You can supply a single action, an array of actions, or the special <tt>:all</tt> or <tt>:none</tt> options. These options are inherited by nested resources.</p></div>
<div class="paragraph"><p>By default, when you use <tt>map.resources</tt> to create a route, Rails generates routes for seven default actions (index, show, create, new, edit, update, and destroy). But each of these routes takes up memory in your application, and causes Rails to generate additional routing logic. Now you can use the <tt>:only</tt> and <tt>:except</tt> options to fine-tune the routes that Rails will generate for resources. You can supply a single action, an array of actions, or the special <tt>:all</tt> or <tt>:none</tt> options. These options are inherited by nested resources.</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>map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>photos<span style="color: #990000">,</span> <span style="color: #990000">:</span>only <span style="color: #990000">=&gt;</span> <span style="color: #990000">[:</span>index<span style="color: #990000">,</span> <span style="color: #990000">:</span>show<span style="color: #990000">]</span>
map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>except <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>destroy
</tt></pre></div></div>
<div class="ilist"><ul>
map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>except <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>destroy</tt></pre></div></div>
<div class="ulist"><ul>
<li>
<p>
Lead Contributor: <a href="http://experthuman.com/">Tom Stuart</a>
@@ -781,7 +771,7 @@ Lead Contributor: <a href="http://experthuman.com/">Tom Stuart</a>
</li>
</ul></div>
<h3 id="_other_action_controller_changes">6.4. Other Action Controller Changes</h3>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
You can now easily <a href="http://m.onkey.org/2008/7/20/rescue-from-dispatching">show a custom error page</a> for exceptions raised while routing a request.
@@ -826,7 +816,7 @@ Polymorphic URLs behave more sensibly if a passed parameter is nil. For example,
</div>
<h2 id="_action_view">7. Action View</h2>
<div class="sectionbody">
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<tt>javascript_include_tag</tt> and <tt>stylesheet_link_tag</tt> support a new <tt>:recursive</tt> option to be used along with <tt>:all</tt>, so that you can load an entire tree of files with a single line of code.
@@ -839,7 +829,7 @@ The included Prototype javascript library has been upgraded to version 1.6.0.3.
</li>
<li>
<p>
<tt>RJS#page.reload</tt> to reload the browser's current location via javascript
<tt>RJS#page.reload</tt> to reload the browser&#8217;s current location via javascript
</p>
</li>
<li>
@@ -851,28 +841,28 @@ The <tt>atom_feed</tt> helper now takes an <tt>:instruct</tt> option to let you
</div>
<h2 id="_action_mailer">8. Action Mailer</h2>
<div class="sectionbody">
<div class="para"><p>Action Mailer now supports mailer layouts. You can make your HTML emails as pretty as your in-browser views by supplying an appropriately-named layout - for example, the <tt>CustomerMailer</tt> class expects to use <tt>layouts/customer_mailer.html.erb</tt>.</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>Action Mailer now supports mailer layouts. You can make your HTML emails as pretty as your in-browser views by supplying an appropriately-named layout - for example, the <tt>CustomerMailer</tt> class expects to use <tt>layouts/customer_mailer.html.erb</tt>.</p></div>
<div class="ulist"><ul>
<li>
<p>
More information:
</p>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<a href="http://ryandaigle.com/articles/2008/9/7/what-s-new-in-edge-rails-mailer-layouts">What's New in Edge Rails: Mailer Layouts</a>
<a href="http://ryandaigle.com/articles/2008/9/7/what-s-new-in-edge-rails-mailer-layouts">What&#8217;s New in Edge Rails: Mailer Layouts</a>
</p>
</li>
</ul></div>
</li>
</ul></div>
<div class="para"><p>Action Mailer now offers built-in support for GMail's SMTP servers, by turning on STARTTLS automatically. This requires Ruby 1.8.7 to be installed.</p></div>
<div class="paragraph"><p>Action Mailer now offers built-in support for GMail&#8217;s SMTP servers, by turning on STARTTLS automatically. This requires Ruby 1.8.7 to be installed.</p></div>
</div>
<h2 id="_active_support">9. Active Support</h2>
<div class="sectionbody">
<div class="para"><p>Active Support now offers built-in memoization for Rails applications, the <tt>each_with_object</tt> method, prefix support on delegates, and various other new utility methods.</p></div>
<div class="paragraph"><p>Active Support now offers built-in memoization for Rails applications, the <tt>each_with_object</tt> method, prefix support on delegates, and various other new utility methods.</p></div>
<h3 id="_memoization">9.1. Memoization</h3>
<div class="para"><p>Memoization is a pattern of initializing a method once and then stashing its value away for repeat use. You've probably used this pattern in your own applications:</p></div>
<div class="paragraph"><p>Memoization is a pattern of initializing a method once and then stashing its value away for repeat use. You&#8217;ve probably used this pattern in your own applications:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -880,9 +870,8 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> full_name
<span style="color: #009900">@full_name</span> <span style="color: #990000">||=</span> <span style="color: #FF0000">"#{first_name} #{last_name}"</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>Memoization lets you handle this task in a declarative fashion:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Memoization lets you handle this task in a declarative fashion:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -893,10 +882,9 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> full_name
<span style="color: #FF0000">"#{first_name} #{last_name}"</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
memoize <span style="color: #990000">:</span>full_name
</tt></pre></div></div>
<div class="para"><p>Other features of memoization include <tt>unmemoize</tt>, <tt>unmemoize_all</tt>, and <tt>memoize_all</tt> to turn memoization on or off.</p></div>
<div class="ilist"><ul>
memoize <span style="color: #990000">:</span>full_name</tt></pre></div></div>
<div class="paragraph"><p>Other features of memoization include <tt>unmemoize</tt>, <tt>unmemoize_all</tt>, and <tt>memoize_all</tt> to turn memoization on or off.</p></div>
<div class="ulist"><ul>
<li>
<p>
Lead Contributor: <a href="http://joshpeek.com/">Josh Peek</a>
@@ -906,10 +894,10 @@ Lead Contributor: <a href="http://joshpeek.com/">Josh Peek</a>
<p>
More information:
</p>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<a href="http://ryandaigle.com/articles/2008/7/16/what-s-new-in-edge-rails-memoization">What's New in Edge Rails: Easy Memoization</a>
<a href="http://ryandaigle.com/articles/2008/7/16/what-s-new-in-edge-rails-memoization">What&#8217;s New in Edge Rails: Easy Memoization</a>
</p>
</li>
<li>
@@ -921,17 +909,16 @@ More information:
</li>
</ul></div>
<h3 id="_tt_each_with_object_tt">9.2. <tt>each_with_object</tt></h3>
<div class="para"><p>The <tt>each_with_object</tt> method provides an alternative to <tt>inject</tt>, using a method backported from Ruby 1.9. It iterates over a collection, passing the current element and the memo into the block.</p></div>
<div class="paragraph"><p>The <tt>each_with_object</tt> method provides an alternative to <tt>inject</tt>, using a method backported from Ruby 1.9. It iterates over a collection, passing the current element and the memo into the block.</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="color: #990000">%</span>w<span style="color: #990000">(</span>foo bar<span style="color: #990000">).</span>each_with_object<span style="color: #990000">(</span><span style="color: #FF0000">{}</span><span style="color: #990000">)</span> <span style="color: #FF0000">{</span> <span style="color: #990000">|</span>str<span style="color: #990000">,</span> hsh<span style="color: #990000">|</span> hsh<span style="color: #990000">[</span>str<span style="color: #990000">]</span> <span style="color: #990000">=</span> str<span style="color: #990000">.</span>upcase <span style="color: #FF0000">}</span> <span style="font-style: italic"><span style="color: #9A1900">#=&gt; {'foo' =&gt; 'FOO', 'bar' =&gt; 'BAR'}</span></span>
</tt></pre></div></div>
<div class="para"><p>Lead Contributor: <a href="http://therealadam.com/">Adam Keys</a></p></div>
<pre><tt><span style="color: #990000">%</span>w<span style="color: #990000">(</span>foo bar<span style="color: #990000">).</span>each_with_object<span style="color: #990000">(</span><span style="color: #FF0000">{}</span><span style="color: #990000">)</span> <span style="color: #FF0000">{</span> <span style="color: #990000">|</span>str<span style="color: #990000">,</span> hsh<span style="color: #990000">|</span> hsh<span style="color: #990000">[</span>str<span style="color: #990000">]</span> <span style="color: #990000">=</span> str<span style="color: #990000">.</span>upcase <span style="color: #FF0000">}</span> <span style="font-style: italic"><span style="color: #9A1900">#=&gt; {'foo' =&gt; 'FOO', 'bar' =&gt; 'BAR'}</span></span></tt></pre></div></div>
<div class="paragraph"><p>Lead Contributor: <a href="http://therealadam.com/">Adam Keys</a></p></div>
<h3 id="_delegates_with_prefixes">9.3. Delegates With Prefixes</h3>
<div class="para"><p>If you delegate behavior from one class to another, you can now specify a prefix that will be used to identify the delegated methods. For example:</p></div>
<div class="paragraph"><p>If you delegate behavior from one class to another, you can now specify a prefix that will be used to identify the delegated methods. For example:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -940,9 +927,8 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Vendor <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
has_one <span style="color: #990000">:</span>account
delegate <span style="color: #990000">:</span>email<span style="color: #990000">,</span> <span style="color: #990000">:</span>password<span style="color: #990000">,</span> <span style="color: #990000">:</span>to <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>account<span style="color: #990000">,</span> <span style="color: #990000">:</span>prefix <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>This will produce delegated methods <tt>vendor#account_email</tt> and <tt>vendor#account_password</tt>. You can also specify a custom prefix:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This will produce delegated methods <tt>vendor#account_email</tt> and <tt>vendor#account_password</tt>. You can also specify a custom prefix:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -951,12 +937,11 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Vendor <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
has_one <span style="color: #990000">:</span>account
delegate <span style="color: #990000">:</span>email<span style="color: #990000">,</span> <span style="color: #990000">:</span>password<span style="color: #990000">,</span> <span style="color: #990000">:</span>to <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>account<span style="color: #990000">,</span> <span style="color: #990000">:</span>prefix <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>owner
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>This will produce delegated methods <tt>vendor#owner_email</tt> and <tt>vendor#owner_password</tt>.</p></div>
<div class="para"><p>Lead Contributor: <a href="http://workingwithrails.com/person/5830-daniel-schierbeck">Daniel Schierbeck</a></p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This will produce delegated methods <tt>vendor#owner_email</tt> and <tt>vendor#owner_password</tt>.</p></div>
<div class="paragraph"><p>Lead Contributor: <a href="http://workingwithrails.com/person/5830-daniel-schierbeck">Daniel Schierbeck</a></p></div>
<h3 id="_other_active_support_changes">9.4. Other Active Support Changes</h3>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
Extensive updates to <tt>ActiveSupport::Multibyte</tt>, including Ruby 1.9 compatibility fixes.
@@ -999,17 +984,17 @@ The included TzInfo library has been upgraded to version 0.3.12.
</li>
<li>
<p>
<tt>ActiveSuport::StringInquirer</tt> gives you a pretty way to test for equality in strings: <tt>ActiveSupport::StringInquirer.new("abc").abc? &#8658; true</tt>
<tt>ActiveSuport::StringInquirer</tt> gives you a pretty way to test for equality in strings: <tt>ActiveSupport::StringInquirer.new("abc").abc? =&gt; true</tt>
</p>
</li>
</ul></div>
</div>
<h2 id="_railties">10. Railties</h2>
<div class="sectionbody">
<div class="para"><p>In Railties (the core code of Rails itself) the biggest changes are in the <tt>config.gems</tt> mechanism.</p></div>
<div class="paragraph"><p>In Railties (the core code of Rails itself) the biggest changes are in the <tt>config.gems</tt> mechanism.</p></div>
<h3 id="_tt_config_gems_tt">10.1. <tt>config.gems</tt></h3>
<div class="para"><p>To avoid deployment issues and make Rails applications more self-contained, it's possible to place copies of all of the gems that your Rails application requires in <tt>/vendor/gems</tt>. This capability first appeared in Rails 2.1, but it's much more flexible and robust in Rails 2.2, handling complicated dependencies between gems. Gem management in Rails includes these commands:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>To avoid deployment issues and make Rails applications more self-contained, it&#8217;s possible to place copies of all of the gems that your Rails application requires in <tt>/vendor/gems</tt>. This capability first appeared in Rails 2.1, but it&#8217;s much more flexible and robust in Rails 2.2, handling complicated dependencies between gems. Gem management in Rails includes these commands:</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>config.gem <em>gem_name</em></tt> in your <tt>config/environment.rb</tt> file
@@ -1046,8 +1031,8 @@ The included TzInfo library has been upgraded to version 0.3.12.
</p>
</li>
</ul></div>
<div class="para"><p>You can unpack or install a single gem by specifying <tt>GEM=<em>gem_name</em></tt> on the command line.</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>You can unpack or install a single gem by specifying <tt>GEM=<em>gem_name</em></tt> on the command line.</p></div>
<div class="ulist"><ul>
<li>
<p>
Lead Contributor: <a href="http://github.com/al2o3cr">Matt Jones</a>
@@ -1057,10 +1042,10 @@ Lead Contributor: <a href="http://github.com/al2o3cr">Matt Jones</a>
<p>
More information:
</p>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<a href="http://ryandaigle.com/articles/2008/4/1/what-s-new-in-edge-rails-gem-dependencies">What's New in Edge Rails: Gem Dependencies</a>
<a href="http://ryandaigle.com/articles/2008/4/1/what-s-new-in-edge-rails-gem-dependencies">What&#8217;s New in Edge Rails: Gem Dependencies</a>
</p>
</li>
<li>
@@ -1077,10 +1062,10 @@ More information:
</li>
</ul></div>
<h3 id="_other_railties_changes">10.2. Other Railties Changes</h3>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
If you're a fan of the <a href="http://code.macournoyer.com/thin/">Thin</a> web server, you'll be happy to know that <tt>script/server</tt> now supports Thin directly.
If you&#8217;re a fan of the <a href="http://code.macournoyer.com/thin/">Thin</a> web server, you&#8217;ll be happy to know that <tt>script/server</tt> now supports Thin directly.
</p>
</li>
<li>
@@ -1090,7 +1075,7 @@ If you're a fan of the <a href="http://code.macournoyer.com/thin/">Thin</a> web
</li>
<li>
<p>
<tt>script/console</tt> now supports a <tt>&#8212;debugger</tt> option
<tt>script/console</tt> now supports a <tt>--debugger</tt> option
</p>
</li>
<li>
@@ -1117,8 +1102,8 @@ To eliminate deprecation warnings and properly handle gem dependencies, Rails no
</div>
<h2 id="_deprecated">11. Deprecated</h2>
<div class="sectionbody">
<div class="para"><p>A few pieces of older code are deprecated in this release:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>A few pieces of older code are deprecated in this release:</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>Rails::SecretKeyGenerator</tt> has been replaced by <tt>ActiveSupport::SecureRandom</tt>
@@ -1126,7 +1111,7 @@ To eliminate deprecation warnings and properly handle gem dependencies, Rails no
</li>
<li>
<p>
<tt>render_component</tt> is deprecated. There's a <a href="http://github.com/rails/render_component/tree/master">render_components plugin</a> available if you need this functionality.
<tt>render_component</tt> is deprecated. There&#8217;s a <a href="http://github.com/rails/render_component/tree/master">render_components plugin</a> available if you need this functionality.
</p>
</li>
<li>
@@ -1143,10 +1128,9 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> partial_with_implicit_local_assignment
<span style="color: #009900">@customer</span> <span style="color: #990000">=</span> Customer<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"Marcel"</span><span style="color: #990000">)</span>
render <span style="color: #990000">:</span>partial <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"customer"</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>Previously the above code made available a local variable called <tt>customer</tt> inside the partial <em>customer</em>. You should explicitly pass all the variables via :locals hash now.</p></div>
<div class="ilist"><ul>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Previously the above code made available a local variable called <tt>customer</tt> inside the partial <em>customer</em>. You should explicitly pass all the variables via :locals hash now.</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>country_select</tt> has been removed. See the <a href="http://www.rubyonrails.org/deprecation/list-of-countries">deprecation page</a> for more information and a plugin replacement.
@@ -1174,14 +1158,14 @@ The <tt>%s</tt> and <tt>%d</tt> interpolation syntax for internationalization is
</li>
<li>
<p>
Durations of fractional months or fractional years are deprecated. Use Ruby's core <tt>Date</tt> and <tt>Time</tt> class arithmetic instead.
Durations of fractional months or fractional years are deprecated. Use Ruby&#8217;s core <tt>Date</tt> and <tt>Time</tt> class arithmetic instead.
</p>
</li>
</ul></div>
</div>
<h2 id="_credits">12. Credits</h2>
<div class="sectionbody">
<div class="para"><p>Release notes compiled by <a href="http://afreshcup.com">Mike Gunderloy</a></p></div>
<div class="paragraph"><p>Release notes compiled by <a href="http://afreshcup.com">Mike Gunderloy</a></p></div>
</div>
</div>

View File

@@ -293,8 +293,8 @@ ul#navMain {
<h1>Action Controller basics</h1>
<div id="preamble">
<div class="sectionbody">
<div class="para"><p>In this guide you will learn how controllers work and how they fit into the request cycle in your application. After reading this guide, you will be able to:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>In this guide you will learn how controllers work and how they fit into the request cycle in your application. After reading this guide, you will be able to:</p></div>
<div class="ulist"><ul>
<li>
<p>
Follow the flow of a request through a controller
@@ -312,17 +312,17 @@ Work with filters to execute code during request processing
</li>
<li>
<p>
Use Action Controller's built-in HTTP authentication
Use Action Controller&#8217;s built-in HTTP authentication
</p>
</li>
<li>
<p>
Stream data directly to the user's browser
Stream data directly to the user&#8217;s browser
</p>
</li>
<li>
<p>
Filter sensitive parameters so they do not appear in the application's log
Filter sensitive parameters so they do not appear in the application&#8217;s log
</p>
</li>
<li>
@@ -335,9 +335,9 @@ Deal with exceptions that may be raised during request processing
</div>
<h2 id="_what_does_a_controller_do">1. What Does a Controller do?</h2>
<div class="sectionbody">
<div class="para"><p>Action Controller is the C in MVC. After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output. Luckily, Action Controller does most of the groundwork for you and uses smart conventions to make this as straight-forward as possible.</p></div>
<div class="para"><p>For most conventional RESTful applications, the controller will receive the request (this is invisible to you as the developer), fetch or save data from a model and use a view to create HTML output. If your controller needs to do things a little differently, that's not a problem, this is just the most common way for a controller to work.</p></div>
<div class="para"><p>A controller can thus be thought of as a middle man between models and views. It makes the model data available to the view so it can display that data to the user, and it saves or updates data from the user to the model.</p></div>
<div class="paragraph"><p>Action Controller is the C in MVC. After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output. Luckily, Action Controller does most of the groundwork for you and uses smart conventions to make this as straight-forward as possible.</p></div>
<div class="paragraph"><p>For most conventional RESTful applications, the controller will receive the request (this is invisible to you as the developer), fetch or save data from a model and use a view to create HTML output. If your controller needs to do things a little differently, that&#8217;s not a problem, this is just the most common way for a controller to work.</p></div>
<div class="paragraph"><p>A controller can thus be thought of as a middle man between models and views. It makes the model data available to the view so it can display that data to the user, and it saves or updates data from the user to the model.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -349,7 +349,7 @@ Deal with exceptions that may be raised during request processing
</div>
<h2 id="_methods_and_actions">2. Methods and Actions</h2>
<div class="sectionbody">
<div class="para"><p>A controller is a Ruby class which inherits from ApplicationController and has methods just like any other class. When your application receives a request, the routing will determine which controller and action to run, then Rails creates an instance of that controller and runs the public method with the same name as the action.</p></div>
<div class="paragraph"><p>A controller is a Ruby class which inherits from ApplicationController and has methods just like any other class. When your application receives a request, the routing will determine which controller and action to run, then Rails creates an instance of that controller and runs the public method with the same name as the action.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -371,10 +371,9 @@ private
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> foo
<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>There's no rule saying a method on a controller has to be an action; they may well be used for other purposes such as filters, which will be covered later in this guide.</p></div>
<div class="para"><p>As an example, if a user goes to <tt>/clients/new</tt> in your application to add a new client, Rails will create an instance of ClientsController and run the <tt>new</tt> method. Note that the empty method from the example above could work just fine because Rails will by default render the <tt>new.html.erb</tt> view unless the action says otherwise. The <tt>new</tt> method could make available to the view a <tt>@client</tt> instance variable by creating a new Client:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>There&#8217;s no rule saying a method on a controller has to be an action; they may well be used for other purposes such as filters, which will be covered later in this guide.</p></div>
<div class="paragraph"><p>As an example, if a user goes to <tt>/clients/new</tt> in your application to add a new client, Rails will create an instance of ClientsController and run the <tt>new</tt> method. Note that the empty method from the example above could work just fine because Rails will by default render the <tt>new.html.erb</tt> view unless the action says otherwise. The <tt>new</tt> method could make available to the view a <tt>@client</tt> instance variable by creating a new Client:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -382,14 +381,13 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> new
<span style="color: #009900">@client</span> <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>new
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The <a href="../layouts_and_rendering.html">Layouts &amp; rendering guide</a> explains this in more detail.</p></div>
<div class="para"><p>ApplicationController inherits from ActionController::Base, which defines a number of helpful methods. This guide will cover some of these, but if you're curious to see what's in there, you can see all of them in the API documentation or in the source itself.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The <a href="../layouts_and_rendering.html">Layouts &amp; rendering guide</a> explains this in more detail.</p></div>
<div class="paragraph"><p>ApplicationController inherits from ActionController::Base, which defines a number of helpful methods. This guide will cover some of these, but if you&#8217;re curious to see what&#8217;s in there, you can see all of them in the API documentation or in the source itself.</p></div>
</div>
<h2 id="_parameters">3. Parameters</h2>
<div class="sectionbody">
<div class="para"><p>You will probably want to access data sent in by the user or other parameters in your controller actions. There are two kinds of parameters possible in a web application. The first are parameters that are sent as part of the URL, called query string parameters. The query string is everything after "?" in the URL. The second type of parameter is usually referred to as POST data. This information usually comes from a HTML form which has been filled in by the user. It's called POST data because it can only be sent as part of an HTTP POST request. Rails does not make any distinction between query string parameters and POST parameters, and both are available in the <tt>params</tt> hash in your controller:</p></div>
<div class="paragraph"><p>You will probably want to access data sent in by the user or other parameters in your controller actions. There are two kinds of parameters possible in a web application. The first are parameters that are sent as part of the URL, called query string parameters. The query string is everything after "?" in the URL. The second type of parameter is usually referred to as POST data. This information usually comes from a HTML form which has been filled in by the user. It&#8217;s called POST data because it can only be sent as part of an HTTP POST request. Rails does not make any distinction between query string parameters and POST parameters, and both are available in the <tt>params</tt> hash in your controller:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -423,10 +421,9 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">end</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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<h3 id="_hash_and_array_parameters">3.1. Hash and Array Parameters</h3>
<div class="para"><p>The params hash is not limited to one-dimensional keys and values. It can contain arrays and (nested) hashes. To send an array of values, append "[]" to the key name:</p></div>
<div class="paragraph"><p>The params hash is not limited to one-dimensional keys and values. It can contain arrays and (nested) hashes. To send an array of values, append "[]" to the key name:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>GET /clients?ids[]=1&amp;ids[]=2&amp;ids[]=3</tt></pre>
@@ -436,11 +433,11 @@ http://www.gnu.org/software/src-highlite -->
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
<td class="content">The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&amp;ids%5b%5d=2&amp;ids%5b%5b=3" as [ and ] are not allowed in URLs. Most of the time you don't have to worry about this because the browser will take care of it for you, and Rails will decode it back when it receives it, but if you ever find yourself having to send those requests to the server manually you have to keep this in mind.</td>
<td class="content">The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&amp;ids%5b%5d=2&amp;ids%5b%5b=3" as [ and ] are not allowed in URLs. Most of the time you don&#8217;t have to worry about this because the browser will take care of it for you, and Rails will decode it back when it receives it, but if you ever find yourself having to send those requests to the server manually you have to keep this in mind.</td>
</tr></table>
</div>
<div class="para"><p>The value of <tt>params[:ids]</tt> will now be <tt>["1", "2", "3"]</tt>. Note that parameter values are always strings; Rails makes no attempt to guess or cast the type.</p></div>
<div class="para"><p>To send a hash you include the key name inside the brackets:</p></div>
<div class="paragraph"><p>The value of <tt>params[:ids]</tt> will now be <tt>["1", "2", "3"]</tt>. Note that parameter values are always strings; Rails makes no attempt to guess or cast the type.</p></div>
<div class="paragraph"><p>To send a hash you include the key name inside the brackets:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;form action="/clients" method="post"&gt;
@@ -450,10 +447,10 @@ http://www.gnu.org/software/src-highlite -->
&lt;input type="text" name="client[address][city]" value="Carrot City" /&gt;
&lt;/form&gt;</tt></pre>
</div></div>
<div class="para"><p>The value of <tt>params[:client]</tt> when this form is submitted will be <tt>{"name" &#8658; "Acme", "phone" &#8658; "12345", "address" &#8658; {"postcode" &#8658; "12345", "city" &#8658; "Carrot City"}}</tt>. Note the nested hash in <tt>params[:client][:address]</tt>.</p></div>
<div class="para"><p>Note that the params hash is actually an instance of HashWithIndifferentAccess from Active Support which is a subclass of Hash which lets you use symbols and strings interchangeably as keys.</p></div>
<div class="paragraph"><p>The value of <tt>params[:client]</tt> when this form is submitted will be <tt>{"name" =&gt; "Acme", "phone" =&gt; "12345", "address" =&gt; {"postcode" =&gt; "12345", "city" =&gt; "Carrot City"}}</tt>. Note the nested hash in <tt>params[:client][:address]</tt>.</p></div>
<div class="paragraph"><p>Note that the params hash is actually an instance of HashWithIndifferentAccess from Active Support which is a subclass of Hash which lets you use symbols and strings interchangeably as keys.</p></div>
<h3 id="_routing_parameters">3.2. Routing Parameters</h3>
<div class="para"><p>The <tt>params</tt> hash will always contain the <tt>:controller</tt> and <tt>:action</tt> keys, but you should use the methods <tt>controller_name</tt> and <tt>action_name</tt> instead to access these values. Any other parameters defined by the routing, such as <tt>:id</tt> will also be available. As an example, consider a listing of clients where the list can show either active or inactive clients. We can add a route which captures the <tt>:status</tt> parameter in a "pretty" URL:</p></div>
<div class="paragraph"><p>The <tt>params</tt> hash will always contain the <tt>:controller</tt> and <tt>:action</tt> keys, but you should use the methods <tt>controller_name</tt> and <tt>action_name</tt> instead to access these values. Any other parameters defined by the routing, such as <tt>:id</tt> will also be available. As an example, consider a listing of clients where the list can show either active or inactive clients. We can add a route which captures the <tt>:status</tt> parameter in a "pretty" URL:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -461,11 +458,10 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># ...</span></span>
map<span style="color: #990000">.</span>connect <span style="color: #FF0000">"/clients/:status"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"clients"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"index"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>foo <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"bar"</span>
<span style="font-style: italic"><span style="color: #9A1900"># ...</span></span>
</tt></pre></div></div>
<div class="para"><p>In this case, when a user opens the URL <tt>/clients/active</tt>, <tt>params[:status]</tt> will be set to "active". When this route is used, <tt>params[:foo]</tt> will also be set to "bar" just like it was passed in the query string in the same way <tt>params[:action]</tt> will contain "index".</p></div>
<span style="font-style: italic"><span style="color: #9A1900"># ...</span></span></tt></pre></div></div>
<div class="paragraph"><p>In this case, when a user opens the URL <tt>/clients/active</tt>, <tt>params[:status]</tt> will be set to "active". When this route is used, <tt>params[:foo]</tt> will also be set to "bar" just like it was passed in the query string in the same way <tt>params[:action]</tt> will contain "index".</p></div>
<h3 id="_tt_default_url_options_tt">3.3. <tt>default_url_options</tt></h3>
<div class="para"><p>You can set global default parameters that will be used when generating URLs with <tt>default_url_options</tt>. To do this, define a method with that name in your controller:</p></div>
<div class="paragraph"><p>You can set global default parameters that will be used when generating URLs with <tt>default_url_options</tt>. To do this, define a method with that name in your controller:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>class ApplicationController &lt; ActionController::Base
@@ -477,12 +473,12 @@ map<span style="color: #990000">.</span>connect <span style="color: #FF0000">"/c
end</tt></pre>
</div></div>
<div class="para"><p>These options will be used as a starting-point when generating, so it's possible they'll be overridden by <tt>url_for</tt>. Because this method is defined in the controller, you can define it on ApplicationController so it would be used for all URL generation, or you could define it on only one controller for all URLs generated there.</p></div>
<div class="paragraph"><p>These options will be used as a starting-point when generating, so it&#8217;s possible they&#8217;ll be overridden by <tt>url_for</tt>. Because this method is defined in the controller, you can define it on ApplicationController so it would be used for all URL generation, or you could define it on only one controller for all URLs generated there.</p></div>
</div>
<h2 id="_session">4. Session</h2>
<div class="sectionbody">
<div class="para"><p>Your application has a session for each user in which you can store small amounts of data that will be persisted between requests. The session is only available in the controller and the view and can use one of a number of different storage mechanisms:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>Your application has a session for each user in which you can store small amounts of data that will be persisted between requests. The session is only available in the controller and the view and can use one of a number of different storage mechanisms:</p></div>
<div class="ulist"><ul>
<li>
<p>
CookieStore - Stores everything on the client.
@@ -504,20 +500,19 @@ ActiveRecordStore - Stores the data in a database using Active Record.
</p>
</li>
</ul></div>
<div class="para"><p>All session stores use a cookie - this is required and Rails does not allow any part of the session to be passed in any other way (e.g. you can't use the query string to pass a session ID) because of security concerns (it's easier to hijack a session when the ID is part of the URL).</p></div>
<div class="para"><p>Most stores use a cookie to store the session ID which is then used to look up the session data on the server. The default and recommended store, the CookieStore, does not store session data on the server, but in the cookie itself. The data is cryptographically signed to make it tamper-proof, but it is not encrypted, so anyone with access to it can read its contents but not edit it (Rails will not accept it if it has been edited). It can only store about 4kB of data - much less than the others - but this is usually enough. Storing large amounts of data is discouraged no matter which session store your application uses. You should especially avoid storing complex objects (anything other than basic Ruby objects, the most common example being model instances) in the session, as the server might not be able to reassemble them between requests, which will result in an error. The CookieStore has the added advantage that it does not require any setting up beforehand - Rails will generate a "secret key" which will be used to sign the cookie when you create the application.</p></div>
<div class="para"><p>Read more about session storage in the <a href="../security.html">Security Guide</a>.</p></div>
<div class="para"><p>If you need a different session storage mechanism, you can change it in the <tt>config/environment.rb</tt> file:</p></div>
<div class="paragraph"><p>All session stores use a cookie - this is required and Rails does not allow any part of the session to be passed in any other way (e.g. you can&#8217;t use the query string to pass a session ID) because of security concerns (it&#8217;s easier to hijack a session when the ID is part of the URL).</p></div>
<div class="paragraph"><p>Most stores use a cookie to store the session ID which is then used to look up the session data on the server. The default and recommended store, the CookieStore, does not store session data on the server, but in the cookie itself. The data is cryptographically signed to make it tamper-proof, but it is not encrypted, so anyone with access to it can read its contents but not edit it (Rails will not accept it if it has been edited). It can only store about 4kB of data - much less than the others - but this is usually enough. Storing large amounts of data is discouraged no matter which session store your application uses. You should especially avoid storing complex objects (anything other than basic Ruby objects, the most common example being model instances) in the session, as the server might not be able to reassemble them between requests, which will result in an error. The CookieStore has the added advantage that it does not require any setting up beforehand - Rails will generate a "secret key" which will be used to sign the cookie when you create the application.</p></div>
<div class="paragraph"><p>Read more about session storage in the <a href="../security.html">Security Guide</a>.</p></div>
<div class="paragraph"><p>If you need a different session storage mechanism, you can change it in the <tt>config/environment.rb</tt> file:</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"># Set to one of [:active_record_store, :drb_store, :mem_cache_store, :cookie_store]</span></span>
config<span style="color: #990000">.</span>action_controller<span style="color: #990000">.</span>session_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>active_record_store
</tt></pre></div></div>
config<span style="color: #990000">.</span>action_controller<span style="color: #990000">.</span>session_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>active_record_store</tt></pre></div></div>
<h3 id="_disabling_the_session">4.1. Disabling the Session</h3>
<div class="para"><p>Sometimes you don't need a session. In this case, you can turn it off to avoid the unnecessary overhead. To do this, use the <tt>session</tt> class method in your controller:</p></div>
<div class="paragraph"><p>Sometimes you don&#8217;t need a session. In this case, you can turn it off to avoid the unnecessary overhead. To do this, use the <tt>session</tt> class method in your controller:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -525,9 +520,8 @@ 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> ApplicationController <span style="color: #990000">&lt;</span> ActionController<span style="color: #990000">::</span>Base
session <span style="color: #990000">:</span>off
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>You can also turn the session on or off for a single controller:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>You can also turn the session on or off for a single controller:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -537,9 +531,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-style: italic"><span style="color: #9A1900"># want to turn it on for log in/out.</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LoginsController <span style="color: #990000">&lt;</span> ActionController<span style="color: #990000">::</span>Base
session <span style="color: #990000">:</span>on
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>Or even for specified actions:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Or even for specified actions:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -547,10 +540,9 @@ 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> ProductsController <span style="color: #990000">&lt;</span> ActionController<span style="color: #990000">::</span>Base
session <span style="color: #990000">:</span>on<span style="color: #990000">,</span> <span style="color: #990000">:</span>only <span style="color: #990000">=&gt;</span> <span style="color: #990000">[:</span>create<span style="color: #990000">,</span> <span style="color: #990000">:</span>update<span style="color: #990000">]</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<h3 id="_accessing_the_session">4.2. Accessing the Session</h3>
<div class="para"><p>In your controller you can access the session through the <tt>session</tt> instance method.</p></div>
<div class="paragraph"><p>In your controller you can access the session through the <tt>session</tt> instance method.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -559,7 +551,7 @@ http://www.gnu.org/software/src-highlite -->
<td class="content">There are two <tt>session</tt> methods, the class and the instance method. The class method which is described above is used to turn the session on and off while the instance method described below is used to access session values.</td>
</tr></table>
</div>
<div class="para"><p>Session values are stored using key/value pairs like a hash:</p></div>
<div class="paragraph"><p>Session values are stored using key/value pairs like a hash:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -576,9 +568,8 @@ private
<span style="color: #009900">@_current_user</span> <span style="color: #990000">||=</span> session<span style="color: #990000">[:</span>current_user_id<span style="color: #990000">]</span> <span style="color: #990000">&amp;&amp;</span> User<span style="color: #990000">.</span>find<span style="color: #990000">(</span>session<span style="color: #990000">[:</span>current_user_id<span style="color: #990000">])</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>To store something in the session, just assign it to the key like a hash:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>To store something in the session, just assign it to the key like a hash:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -595,9 +586,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">end</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>To remove something from the session, assign that key to be <tt>nil</tt>:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>To remove something from the session, assign that key to be <tt>nil</tt>:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -612,11 +602,10 @@ http://www.gnu.org/software/src-highlite -->
redirect_to root_url
<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>To reset the entire session, use <tt>reset_session</tt>.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>To reset the entire session, use <tt>reset_session</tt>.</p></div>
<h3 id="_the_flash">4.3. The flash</h3>
<div class="para"><p>The flash is a special part of the session which is cleared with each request. This means that values stored there will only be available in the next request, which is useful for storing error messages etc. It is accessed in much the same way as the session, like a hash. Let's use the act of logging out as an example. The controller can send a message which will be displayed to the user on the next request:</p></div>
<div class="paragraph"><p>The flash is a special part of the session which is cleared with each request. This means that values stored there will only be available in the next request, which is useful for storing error messages etc. It is accessed in much the same way as the session, like a hash. Let&#8217;s use the act of logging out as an example. The controller can send a message which will be displayed to the user on the next request:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -630,9 +619,8 @@ http://www.gnu.org/software/src-highlite -->
redirect_to root_url
<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>The <tt>destroy</tt> action redirects to the application's <tt>root_url</tt>, where the message will be displayed. Note that it's entirely up to the next action to decide what, if anything, it will do with what the previous action put in the flash. It's conventional to display eventual errors or notices from the flash in the application's layout:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The <tt>destroy</tt> action redirects to the application&#8217;s <tt>root_url</tt>, where the message will be displayed. Note that it&#8217;s entirely up to the next action to decide what, if anything, it will do with what the previous action put in the flash. It&#8217;s conventional to display eventual errors or notices from the flash in the application&#8217;s layout:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;html&gt;
@@ -648,8 +636,8 @@ http://www.gnu.org/software/src-highlite -->
&lt;/body&gt;
&lt;/html&gt;</tt></pre>
</div></div>
<div class="para"><p>This way, if an action sets an error or a notice message, the layout will display it automatically.</p></div>
<div class="para"><p>If you want a flash value to be carried over to another request, use the <tt>keep</tt> method:</p></div>
<div class="paragraph"><p>This way, if an action sets an error or a notice message, the layout will display it automatically.</p></div>
<div class="paragraph"><p>If you want a flash value to be carried over to another request, use the <tt>keep</tt> method:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -665,10 +653,9 @@ http://www.gnu.org/software/src-highlite -->
redirect_to users_url
<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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<h4 id="_tt_flash_now_tt">4.3.1. <tt>flash.now</tt></h4>
<div class="para"><p>By default, adding values to the flash will make them available to the next request, but sometimes you may want to access those values in the same request. For example, if the <tt>create</tt> action fails to save a resource and you render the <tt>new</tt> template directly, that's not going to result in a new request, but you may still want to display a message using the flash. To do this, you can use <tt>flash.now</tt> in the same way you use the normal <tt>flash</tt>:</p></div>
<div class="paragraph"><p>By default, adding values to the flash will make them available to the next request, but sometimes you may want to access those values in the same request. For example, if the <tt>create</tt> action fails to save a resource and you render the <tt>new</tt> template directly, that&#8217;s not going to result in a new request, but you may still want to display a message using the flash. To do this, you can use <tt>flash.now</tt> in the same way you use the normal <tt>flash</tt>:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -686,12 +673,11 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">end</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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
</div>
<h2 id="_cookies">5. Cookies</h2>
<div class="sectionbody">
<div class="para"><p>Your application can store small amounts of data on the client - called cookies - that will be persisted across requests and even sessions. Rails provides easy access to cookies via the <tt>cookies</tt> method, which - much like the <tt>session</tt> - works like a hash:</p></div>
<div class="paragraph"><p>Your application can store small amounts of data on the client - called cookies - that will be persisted across requests and even sessions. Rails provides easy access to cookies via the <tt>cookies</tt> method, which - much like the <tt>session</tt> - works like a hash:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -721,13 +707,12 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">end</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>Note that while for session values you set the key to <tt>nil</tt>, to delete a cookie value you should use <tt>cookies.delete(:key)</tt>.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Note that while for session values you set the key to <tt>nil</tt>, to delete a cookie value you should use <tt>cookies.delete(:key)</tt>.</p></div>
</div>
<h2 id="_filters">6. Filters</h2>
<div class="sectionbody">
<div class="para"><p>Filters are methods that are run before, after or "around" a controller action. For example, one filter might check to see if the logged in user has the right credentials to access that particular controller or action. Filters are inherited, so if you set a filter on ApplicationController, it will be run on every controller in your application. A common, simple filter is one which requires that a user is logged in for an action to be run. You can define the filter method this way:</p></div>
<div class="paragraph"><p>Filters are methods that are run before, after or "around" a controller action. For example, one filter might check to see if the logged in user has the right credentials to access that particular controller or action. Filters are inherited, so if you set a filter on ApplicationController, it will be run on every controller in your application. A common, simple filter is one which requires that a user is logged in for an action to be run. You can define the filter method this way:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -753,9 +738,8 @@ private
<span style="color: #990000">!!</span>current_user
<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>The method simply stores an error message in the flash and redirects to the login form if the user is not logged in. If a before filter (a filter which is run before the action) renders or redirects, the action will not run. If there are additional filters scheduled to run after the rendering or redirecting filter, they are also cancelled. To use this filter in a controller, use the <tt>before_filter</tt> method:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The method simply stores an error message in the flash and redirects to the login form if the user is not logged in. If a before filter (a filter which is run before the action) renders or redirects, the action will not run. If there are additional filters scheduled to run after the rendering or redirecting filter, they are also cancelled. To use this filter in a controller, use the <tt>before_filter</tt> method:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -765,9 +749,8 @@ http://www.gnu.org/software/src-highlite -->
before_filter <span style="color: #990000">:</span>require_login
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>In this example, the filter is added to ApplicationController and thus all controllers in the application. This will make everything in the application require the user to be logged in in order to use it. For obvious reasons (the user wouldn't be able to log in in the first place!), not all controllers or actions should require this. You can prevent this filter from running before particular actions with <tt>skip_before_filter</tt>:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>In this example, the filter is added to ApplicationController and thus all controllers in the application. This will make everything in the application require the user to be logged in in order to use it. For obvious reasons (the user wouldn&#8217;t be able to log in in the first place!), not all controllers or actions should require this. You can prevent this filter from running before particular actions with <tt>skip_before_filter</tt>:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -777,11 +760,10 @@ http://www.gnu.org/software/src-highlite -->
skip_before_filter <span style="color: #990000">:</span>require_login<span style="color: #990000">,</span> <span style="color: #990000">:</span>only <span style="color: #990000">=&gt;</span> <span style="color: #990000">[:</span>new<span style="color: #990000">,</span> <span style="color: #990000">:</span>create<span style="color: #990000">]</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>Now, the LoginsController's <tt>new</tt> and <tt>create</tt> actions will work as before without requiring the user to be logged in. The <tt>:only</tt> option is used to only skip this filter for these actions, and there is also an <tt>:except</tt> option which works the other way. These options can be used when adding filters too, so you can add a filter which only runs for selected actions in the first place.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Now, the LoginsController&#8217;s <tt>new</tt> and <tt>create</tt> actions will work as before without requiring the user to be logged in. The <tt>:only</tt> option is used to only skip this filter for these actions, and there is also an <tt>:except</tt> option which works the other way. These options can be used when adding filters too, so you can add a filter which only runs for selected actions in the first place.</p></div>
<h3 id="_after_filters_and_around_filters">6.1. After Filters and Around Filters</h3>
<div class="para"><p>In addition to the before filters, you can run filters after an action has run or both before and after. The after filter is similar to the before filter, but because the action has already been run it has access to the response data that's about to be sent to the client. Obviously, after filters can not stop the action from running. Around filters are responsible for running the action, but they can choose not to, which is the around filter's way of stopping it.</p></div>
<div class="paragraph"><p>In addition to the before filters, you can run filters after an action has run or both before and after. The after filter is similar to the before filter, but because the action has already been run it has access to the response data that&#8217;s about to be sent to the client. Obviously, after filters can not stop the action from running. Around filters are responsible for running the action, but they can choose not to, which is the around filter&#8217;s way of stopping it.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -802,11 +784,10 @@ private
<span style="font-weight: bold"><span style="color: #0000FF">raise</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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<h3 id="_other_ways_to_use_filters">6.2. Other Ways to Use Filters</h3>
<div class="para"><p>While the most common way to use filters is by creating private methods and using *_filter to add them, there are two other ways to do the same thing.</p></div>
<div class="para"><p>The first is to use a block directly with the *_filter methods. The block receives the controller as an argument, and the <tt>require_login</tt> filter from above could be rewritten to use a block:</p></div>
<div class="paragraph"><p>While the most common way to use filters is by creating private methods and using *_filter to add them, there are two other ways to do the same thing.</p></div>
<div class="paragraph"><p>The first is to use a block directly with the *_filter methods. The block receives the controller as an argument, and the <tt>require_login</tt> filter from above could be rewritten to use a block:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -816,10 +797,9 @@ http://www.gnu.org/software/src-highlite -->
before_filter <span style="color: #FF0000">{</span> <span style="color: #990000">|</span>controller<span style="color: #990000">|</span> redirect_to new_login_url <span style="font-weight: bold"><span style="color: #0000FF">unless</span></span> controller<span style="color: #990000">.</span>send<span style="color: #990000">(:</span>logged_in?<span style="color: #990000">)</span> <span style="color: #FF0000">}</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>Note that the filter in this case uses <tt>send</tt> because the <tt>logged_in?</tt> method is private and the filter is not run in the scope of the controller. This is not the recommended way to implement this particular filter, but in more simple cases it might be useful.</p></div>
<div class="para"><p>The second way is to use a class (actually, any object that responds to the right methods will do) to handle the filtering. This is useful in cases that are more complex than can not be implemented in a readable and reusable way using the two other methods. As an example, you could rewrite the login filter again to use a class:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Note that the filter in this case uses <tt>send</tt> because the <tt>logged_in?</tt> method is private and the filter is not run in the scope of the controller. This is not the recommended way to implement this particular filter, but in more simple cases it might be useful.</p></div>
<div class="paragraph"><p>The second way is to use a class (actually, any object that responds to the right methods will do) to handle the filtering. This is useful in cases that are more complex than can not be implemented in a readable and reusable way using the two other methods. As an example, you could rewrite the login filter again to use a class:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -840,15 +820,14 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">end</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>Again, this is not an ideal example for this filter, because it's not run in the scope of the controller but gets the controller passed as an argument. The filter class has a class method <tt>filter</tt> which gets run before or after the action, depending on if it's a before or after filter. Classes used as around filters can also use the same <tt>filter</tt> method, which will get run in the same way. The method must <tt>yield</tt> to execute the action. Alternatively, it can have both a <tt>before</tt> and an <tt>after</tt> method that are run before and after the action.</p></div>
<div class="para"><p>The Rails API documentation has <a href="http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html">more information on using filters</a>.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Again, this is not an ideal example for this filter, because it&#8217;s not run in the scope of the controller but gets the controller passed as an argument. The filter class has a class method <tt>filter</tt> which gets run before or after the action, depending on if it&#8217;s a before or after filter. Classes used as around filters can also use the same <tt>filter</tt> method, which will get run in the same way. The method must <tt>yield</tt> to execute the action. Alternatively, it can have both a <tt>before</tt> and an <tt>after</tt> method that are run before and after the action.</p></div>
<div class="paragraph"><p>The Rails API documentation has <a href="http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html">more information on using filters</a>.</p></div>
</div>
<h2 id="_verification">7. Verification</h2>
<div class="sectionbody">
<div class="para"><p>Verifications make sure certain criteria are met in order for a controller or action to run. They can specify that a certain key (or several keys in the form of an array) is present in the <tt>params</tt>, <tt>session</tt> or <tt>flash</tt> hashes or that a certain HTTP method was used or that the request was made using XMLHTTPRequest (Ajax). The default action taken when these criteria are not met is to render a 400 Bad Request response, but you can customize this by specifying a redirect URL or rendering something else and you can also add flash messages and HTTP headers to the response. It is described in the <a href="http://api.rubyonrails.org/classes/ActionController/Verification/ClassMethods.html">API documentation</a> as "essentially a special kind of before_filter".</p></div>
<div class="para"><p>Here's an example of using verification to make sure the user supplies a username and a password in order to log in:</p></div>
<div class="paragraph"><p>Verifications make sure certain criteria are met in order for a controller or action to run. They can specify that a certain key (or several keys in the form of an array) is present in the <tt>params</tt>, <tt>session</tt> or <tt>flash</tt> hashes or that a certain HTTP method was used or that the request was made using XMLHTTPRequest (Ajax). The default action taken when these criteria are not met is to render a 400 Bad Request response, but you can customize this by specifying a redirect URL or rendering something else and you can also add flash messages and HTTP headers to the response. It is described in the <a href="http://api.rubyonrails.org/classes/ActionController/Verification/ClassMethods.html">API documentation</a> as "essentially a special kind of before_filter".</p></div>
<div class="paragraph"><p>Here&#8217;s an example of using verification to make sure the user supplies a username and a password in order to log in:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -870,9 +849,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">end</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>Now the <tt>create</tt> action won't run unless the "username" and "password" parameters are present, and if they're not, an error message will be added to the flash and the <tt>new</tt> action will be rendered. But there's something rather important missing from the verification above: It will be used for <strong>every</strong> action in LoginsController, which is not what we want. You can limit which actions it will be used for with the <tt>:only</tt> and <tt>:except</tt> options just like a filter:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Now the <tt>create</tt> action won&#8217;t run unless the "username" and "password" parameters are present, and if they&#8217;re not, an error message will be added to the flash and the <tt>new</tt> action will be rendered. But there&#8217;s something rather important missing from the verification above: It will be used for <strong>every</strong> action in LoginsController, which is not what we want. You can limit which actions it will be used for with the <tt>:only</tt> and <tt>:except</tt> options just like a filter:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -885,13 +863,12 @@ http://www.gnu.org/software/src-highlite -->
<span style="color: #990000">:</span>add_flash <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span><span style="color: #990000">:</span>error <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"Username and password required to log in"</span><span style="color: #FF0000">}</span><span style="color: #990000">,</span>
<span style="color: #990000">:</span>only <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>create <span style="font-style: italic"><span style="color: #9A1900"># Only run this verification for the "create" action</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
</div>
<h2 id="_request_forgery_protection">8. Request Forgery Protection</h2>
<div class="sectionbody">
<div class="para"><p>Cross-site request forgery is a type of attack in which a site tricks a user into making requests on another site, possibly adding, modifying or deleting data on that site without the user's knowledge or permission. The first step to avoid this is to make sure all "destructive" actions (create, update and destroy) can only be accessed with non-GET requests. If you're following RESTful conventions you're already doing this. However, a malicious site can still send a non-GET request to your site quite easily, and that's where the request forgery protection comes in. As the name says, it protects from forged requests. The way this is done is to add a non-guessable token which is only known to your server to each request. This way, if a request comes in without the proper token, it will be denied access.</p></div>
<div class="para"><p>If you generate a form like this:</p></div>
<div class="paragraph"><p>Cross-site request forgery is a type of attack in which a site tricks a user into making requests on another site, possibly adding, modifying or deleting data on that site without the user&#8217;s knowledge or permission. The first step to avoid this is to make sure all "destructive" actions (create, update and destroy) can only be accessed with non-GET requests. If you&#8217;re following RESTful conventions you&#8217;re already doing this. However, a malicious site can still send a non-GET request to your site quite easily, and that&#8217;s where the request forgery protection comes in. As the name says, it protects from forged requests. The way this is done is to add a non-guessable token which is only known to your server to each request. This way, if a request comes in without the proper token, it will be denied access.</p></div>
<div class="paragraph"><p>If you generate a form like this:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -900,9 +877,8 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #FF0000">&lt;% form_for @user do |f| -%&gt;</span>
<span style="color: #FF0000">&lt;%= f.text_field :username %&gt;</span>
<span style="color: #FF0000">&lt;%= f.text_field :password -%&gt;</span>
<span style="color: #FF0000">&lt;% end -%&gt;</span>
</tt></pre></div></div>
<div class="para"><p>You will see how the token gets added as a hidden field:</p></div>
<span style="color: #FF0000">&lt;% end -%&gt;</span></tt></pre></div></div>
<div class="paragraph"><p>You will see how the token gets added as a hidden field:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -911,22 +887,21 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">&lt;form</span></span> <span style="color: #009900">action</span><span style="color: #990000">=</span><span style="color: #FF0000">"/users/1"</span> <span style="color: #009900">method</span><span style="color: #990000">=</span><span style="color: #FF0000">"post"</span><span style="font-weight: bold"><span style="color: #0000FF">&gt;</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">&lt;div&gt;</span></span><span style="font-style: italic"><span style="color: #9A1900">&lt;!-- ... --&gt;</span></span><span style="font-weight: bold"><span style="color: #0000FF">&lt;input</span></span> <span style="color: #009900">type</span><span style="color: #990000">=</span><span style="color: #FF0000">"hidden"</span> <span style="color: #009900">value</span><span style="color: #990000">=</span><span style="color: #FF0000">"67250ab105eb5ad10851c00a5621854a23af5489"</span> <span style="color: #009900">name</span><span style="color: #990000">=</span><span style="color: #FF0000">"authenticity_token"</span><span style="font-weight: bold"><span style="color: #0000FF">/&gt;&lt;/div&gt;</span></span>
<span style="font-style: italic"><span style="color: #9A1900">&lt;!-- Fields --&gt;</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">&lt;/form&gt;</span></span>
</tt></pre></div></div>
<div class="para"><p>Rails adds this token to every form that's generated using the <a href="../form_helpers.html">form helpers</a>, so most of the time you don't have to worry about it. If you're writing a form manually or need to add the token for another reason, it's available through the method <tt>form_authenticity_token</tt>:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">&lt;/form&gt;</span></span></tt></pre></div></div>
<div class="paragraph"><p>Rails adds this token to every form that&#8217;s generated using the <a href="../form_helpers.html">form helpers</a>, so most of the time you don&#8217;t have to worry about it. If you&#8217;re writing a form manually or need to add the token for another reason, it&#8217;s available through the method <tt>form_authenticity_token</tt>:</p></div>
<div class="listingblock">
<div class="title">Example: Add a JavaScript variable containing the token for use with Ajax</div>
<div class="title">Add a JavaScript variable containing the token for use with Ajax</div>
<div class="content">
<pre><tt>&lt;%= javascript_tag "MyApp.authenticity_token = '#{form_authenticity_token}'" %&gt;</tt></pre>
</div></div>
<div class="para"><p>The <a href="../security.html">Security Guide</a> has more about this and a lot of other security-related issues that you should be aware of when developing a web application.</p></div>
<div class="paragraph"><p>The <a href="../security.html">Security Guide</a> has more about this and a lot of other security-related issues that you should be aware of when developing a web application.</p></div>
</div>
<h2 id="_the_tt_request_tt_and_tt_response_tt_objects">9. The <tt>request</tt> and <tt>response</tt> Objects</h2>
<div class="sectionbody">
<div class="para"><p>In every controller there are two accessor methods pointing to the request and the response objects associated with the request cycle that is currently in execution. The <tt>request</tt> method contains an instance of AbstractRequest and the <tt>response</tt> method returns a <tt>response</tt> object representing what is going to be sent back to the client.</p></div>
<div class="paragraph"><p>In every controller there are two accessor methods pointing to the request and the response objects associated with the request cycle that is currently in execution. The <tt>request</tt> method contains an instance of AbstractRequest and the <tt>response</tt> method returns a <tt>response</tt> object representing what is going to be sent back to the client.</p></div>
<h3 id="_the_tt_request_tt_object">9.1. The <tt>request</tt> Object</h3>
<div class="para"><p>The request object contains a lot of useful information about the request coming in from the client. To get a full list of the available methods, refer to the <a href="http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html">API documentation</a>. Among the properties that you can access on this object are:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>The request object contains a lot of useful information about the request coming in from the client. To get a full list of the available methods, refer to the <a href="http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html">API documentation</a>. Among the properties that you can access on this object are:</p></div>
<div class="ulist"><ul>
<li>
<p>
host - The hostname used for this request.
@@ -934,7 +909,7 @@ host - The hostname used for this request.
</li>
<li>
<p>
domain(n=2) - The hostname's first <tt>n</tt> segments, starting from the right (the TLD)
domain(n=2) - The hostname&#8217;s first <tt>n</tt> segments, starting from the right (the TLD)
</p>
</li>
<li>
@@ -984,10 +959,10 @@ url - The entire URL used for the request.
</li>
</ul></div>
<h4 id="_tt_path_parameters_tt_tt_query_parameters_tt_and_tt_request_parameters_tt">9.1.1. <tt>path_parameters</tt>, <tt>query_parameters</tt> and <tt>request_parameters</tt></h4>
<div class="para"><p>Rails collects all of the parameters sent along with the request in the <tt>params</tt> hash, whether they are sent as part of the query string or the post body. The request object has three accessors that give you access to these parameters depending on where they came from. The <tt>query_parameters</tt> hash contains parameters that were sent as part of the query string while the <tt>request_parameters</tt> hash contains parameters sent as part of the post body. The <tt>path_parameters</tt> hash contains parameters that were recognized by the routing as being part of the path leading to this particular controller and action.</p></div>
<div class="paragraph"><p>Rails collects all of the parameters sent along with the request in the <tt>params</tt> hash, whether they are sent as part of the query string or the post body. The request object has three accessors that give you access to these parameters depending on where they came from. The <tt>query_parameters</tt> hash contains parameters that were sent as part of the query string while the <tt>request_parameters</tt> hash contains parameters sent as part of the post body. The <tt>path_parameters</tt> hash contains parameters that were recognized by the routing as being part of the path leading to this particular controller and action.</p></div>
<h3 id="_the_tt_response_tt_object">9.2. The <tt>response</tt> Object</h3>
<div class="para"><p>The response object is not usually used directly, but is built up during the execution of the action and rendering of the data that is being sent back to the user, but sometimes - like in an after filter - it can be useful to access the response directly. Some of these accessor methods also have setters, allowing you to change their values.</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>The response object is not usually used directly, but is built up during the execution of the action and rendering of the data that is being sent back to the user, but sometimes - like in an after filter - it can be useful to access the response directly. Some of these accessor methods also have setters, allowing you to change their values.</p></div>
<div class="ulist"><ul>
<li>
<p>
body - This is the string of data being sent back to the client. This is most often HTML.
@@ -1020,18 +995,17 @@ headers - Headers used for the response.
</li>
</ul></div>
<h4 id="_setting_custom_headers">9.2.1. Setting Custom Headers</h4>
<div class="para"><p>If you want to set custom headers for a response then <tt>response.headers</tt> is the place to do it. The headers attribute is a hash which maps header names to their values, and Rails will set some of them - like "Content-Type" - automatically. If you want to add or change a header, just assign it to <tt>headers</tt> with the name and value:</p></div>
<div class="paragraph"><p>If you want to set custom headers for a response then <tt>response.headers</tt> is the place to do it. The headers attribute is a hash which maps header names to their values, and Rails will set some of them - like "Content-Type" - automatically. If you want to add or change a header, just assign it to <tt>headers</tt> with the name and value:</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>response<span style="color: #990000">.</span>headers<span style="color: #990000">[</span><span style="color: #FF0000">"Content-Type"</span><span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"application/pdf"</span>
</tt></pre></div></div>
<pre><tt>response<span style="color: #990000">.</span>headers<span style="color: #990000">[</span><span style="color: #FF0000">"Content-Type"</span><span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"application/pdf"</span></tt></pre></div></div>
</div>
<h2 id="_http_basic_authentication">10. HTTP Basic Authentication</h2>
<div class="sectionbody">
<div class="para"><p>Rails comes with built-in HTTP Basic authentication. This is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, consider an administration section which will only be available by entering a username and a password into the browser's HTTP Basic dialog window. Using the built-in authentication is quite easy and only requires you to use one method, <tt>authenticate_or_request_with_http_basic</tt>.</p></div>
<div class="paragraph"><p>Rails comes with built-in HTTP Basic authentication. This is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, consider an administration section which will only be available by entering a username and a password into the browser&#8217;s HTTP Basic dialog window. Using the built-in authentication is quite easy and only requires you to use one method, <tt>authenticate_or_request_with_http_basic</tt>.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1051,14 +1025,13 @@ private
<span style="font-weight: bold"><span style="color: #0000FF">end</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>With this in place, you can create namespaced controllers that inherit from AdminController. The before filter will thus be run for all actions in those controllers, protecting them with HTTP Basic authentication.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>With this in place, you can create namespaced controllers that inherit from AdminController. The before filter will thus be run for all actions in those controllers, protecting them with HTTP Basic authentication.</p></div>
</div>
<h2 id="_streaming_and_file_downloads">11. Streaming and File Downloads</h2>
<div class="sectionbody">
<div class="para"><p>Sometimes you may want to send a file to the user instead of rendering an HTML page. All controllers in Rails have the <tt>send_data</tt> and the <tt>send_file</tt> methods, that will both stream data to the client. <tt>send_file</tt> is a convenience method which lets you provide the name of a file on the disk and it will stream the contents of that file for you.</p></div>
<div class="para"><p>To stream data to the client, use <tt>send_data</tt>:</p></div>
<div class="paragraph"><p>Sometimes you may want to send a file to the user instead of rendering an HTML page. All controllers in Rails have the <tt>send_data</tt> and the <tt>send_file</tt> methods, that will both stream data to the client. <tt>send_file</tt> is a convenience method which lets you provide the name of a file on the disk and it will stream the contents of that file for you.</p></div>
<div class="paragraph"><p>To stream data to the client, use <tt>send_data</tt>:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1084,11 +1057,10 @@ private
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span><span style="color: #990000">.</span>render
<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>The <tt>download_pdf</tt> action in the example above will call a private method which actually generates the file (a PDF document) and returns it as a string. This string will then be streamed to the client as a file download and a filename will be suggested to the user. Sometimes when streaming files to the user, you may not want them to download the file. Take images, for example, which can be embedded into HTML pages. To tell the browser a file is not meant to be downloaded, you can set the <tt>:disposition</tt> option to "inline". The opposite and default value for this option is "attachment".</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The <tt>download_pdf</tt> action in the example above will call a private method which actually generates the file (a PDF document) and returns it as a string. This string will then be streamed to the client as a file download and a filename will be suggested to the user. Sometimes when streaming files to the user, you may not want them to download the file. Take images, for example, which can be embedded into HTML pages. To tell the browser a file is not meant to be downloaded, you can set the <tt>:disposition</tt> option to "inline". The opposite and default value for this option is "attachment".</p></div>
<h3 id="_sending_files">11.1. Sending Files</h3>
<div class="para"><p>If you want to send a file that already exists on disk, use the <tt>send_file</tt> method. This is usually not recommended, but can be useful if you want to perform some authentication before letting the user download the file.</p></div>
<div class="paragraph"><p>If you want to send a file that already exists on disk, use the <tt>send_file</tt> method. This is usually not recommended, but can be useful if you want to perform some authentication before letting the user download the file.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1102,15 +1074,14 @@ http://www.gnu.org/software/src-highlite -->
send_data<span style="color: #990000">(</span><span style="color: #FF0000">"#{RAILS_ROOT}/files/clients/#{client.id}.pdf"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>filename <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"#{client.name}.pdf"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>type <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"application/pdf"</span><span style="color: #990000">)</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>This will read and stream the file 4Kb at the time, avoiding loading the entire file into memory at once. You can turn off streaming with the <tt>:stream</tt> option or adjust the block size with the <tt>:buffer_size</tt> option.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This will read and stream the file 4Kb at the time, avoiding loading the entire file into memory at once. You can turn off streaming with the <tt>:stream</tt> option or adjust the block size with the <tt>:buffer_size</tt> option.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/warning.png" alt="Warning" />
</td>
<td class="content">Be careful when using (or just don't use) "outside" data (params, cookies, etc) to locate the file on disk, as this is a security risk that might allow someone to gain access to files they are not meant to see.</td>
<td class="content">Be careful when using (or just don&#8217;t use) "outside" data (params, cookies, etc) to locate the file on disk, as this is a security risk that might allow someone to gain access to files they are not meant to see.</td>
</tr></table>
</div>
<div class="admonitionblock">
@@ -1122,7 +1093,7 @@ http://www.gnu.org/software/src-highlite -->
</tr></table>
</div>
<h3 id="_restful_downloads">11.2. RESTful Downloads</h3>
<div class="para"><p>While <tt>send_data</tt> works just fine, if you are creating a RESTful application having separate actions for file downloads is usually not necessary. In REST terminology, the PDF file from the example above can be considered just another representation of the client resource. Rails provides an easy and quite sleek way of doing "RESTful downloads". Here's how you can rewrite the example so that the PDF download is a part of the <tt>show</tt> action, without any streaming:</p></div>
<div class="paragraph"><p>While <tt>send_data</tt> works just fine, if you are creating a RESTful application having separate actions for file downloads is usually not necessary. In REST terminology, the PDF file from the example above can be considered just another representation of the client resource. Rails provides an easy and quite sleek way of doing "RESTful downloads". Here&#8217;s how you can rewrite the example so that the PDF download is a part of the <tt>show</tt> action, without any streaming:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1140,16 +1111,14 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">end</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>In order for this example to work, you have to add the PDF MIME type to Rails. This can be done by adding the following line to the file <tt>config/initializers/mime_types.rb</tt>:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>In order for this example to work, you have to add the PDF MIME type to Rails. This can be done by adding the following line to the file <tt>config/initializers/mime_types.rb</tt>:</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>Mime<span style="color: #990000">::</span>Type<span style="color: #990000">.</span>register <span style="color: #FF0000">"application/pdf"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>pdf
</tt></pre></div></div>
<pre><tt>Mime<span style="color: #990000">::</span>Type<span style="color: #990000">.</span>register <span style="color: #FF0000">"application/pdf"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>pdf</tt></pre></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -1158,7 +1127,7 @@ http://www.gnu.org/software/src-highlite -->
<td class="content">Configuration files are not reloaded on each request, so you have to restart the server in order for their changes to take effect.</td>
</tr></table>
</div>
<div class="para"><p>Now the user can request to get a PDF version of a client just by adding ".pdf" to the URL:</p></div>
<div class="paragraph"><p>Now the user can request to get a PDF version of a client just by adding ".pdf" to the URL:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>GET /clients/1.pdf</tt></pre>
@@ -1166,7 +1135,7 @@ http://www.gnu.org/software/src-highlite -->
</div>
<h2 id="_parameter_filtering">12. Parameter Filtering</h2>
<div class="sectionbody">
<div class="para"><p>Rails keeps a log file for each environment (development, test and production) in the <tt>log</tt> folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. The <tt>filter_parameter_logging</tt> method can be used to filter out sensitive information from the log. It works by replacing certain values in the <tt>params</tt> hash with "[FILTERED]" as they are written to the log. As an example, let's see how to filter all parameters with keys that include "password":</p></div>
<div class="paragraph"><p>Rails keeps a log file for each environment (development, test and production) in the <tt>log</tt> folder. These are extremely useful when debugging what&#8217;s actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. The <tt>filter_parameter_logging</tt> method can be used to filter out sensitive information from the log. It works by replacing certain values in the <tt>params</tt> hash with "[FILTERED]" as they are written to the log. As an example, let&#8217;s see how to filter all parameters with keys that include "password":</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1176,18 +1145,17 @@ http://www.gnu.org/software/src-highlite -->
filter_parameter_logging <span style="color: #990000">:</span>password
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The method works recursively through all levels of the params hash and takes an optional second parameter which is used as the replacement string if present. It can also take a block which receives each key in turn and replaces those for which the block returns true.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The method works recursively through all levels of the params hash and takes an optional second parameter which is used as the replacement string if present. It can also take a block which receives each key in turn and replaces those for which the block returns true.</p></div>
</div>
<h2 id="_rescue">13. Rescue</h2>
<div class="sectionbody">
<div class="para"><p>Most likely your application is going to contain bugs or otherwise throw an exception that needs to be handled. For example, if the user follows a link to a resource that no longer exists in the database, Active Record will throw the ActiveRecord::RecordNotFound exception. Rails' default exception handling displays a 500 Server Error message for all exceptions. If the request was made locally, a nice traceback and some added information gets displayed so you can figure out what went wrong and deal with it. If the request was remote Rails will just display a simple "500 Server Error" message to the user, or a "404 Not Found" if there was a routing error or a record could not be found. Sometimes you might want to customize how these errors are caught and how they're displayed to the user. There are several levels of exception handling available in a Rails application:</p></div>
<div class="paragraph"><p>Most likely your application is going to contain bugs or otherwise throw an exception that needs to be handled. For example, if the user follows a link to a resource that no longer exists in the database, Active Record will throw the ActiveRecord::RecordNotFound exception. Rails' default exception handling displays a 500 Server Error message for all exceptions. If the request was made locally, a nice traceback and some added information gets displayed so you can figure out what went wrong and deal with it. If the request was remote Rails will just display a simple "500 Server Error" message to the user, or a "404 Not Found" if there was a routing error or a record could not be found. Sometimes you might want to customize how these errors are caught and how they&#8217;re displayed to the user. There are several levels of exception handling available in a Rails application:</p></div>
<h3 id="_the_default_500_and_404_templates">13.1. The Default 500 and 404 Templates</h3>
<div class="para"><p>By default a production application will render either a 404 or a 500 error message. These messages are contained in static HTML files in the <tt>public</tt> folder, in <tt>404.html</tt> and <tt>500.html</tt> respectively. You can customize these files to add some extra information and layout, but remember that they are static; i.e. you can't use RHTML or layouts in them, just plain HTML.</p></div>
<div class="paragraph"><p>By default a production application will render either a 404 or a 500 error message. These messages are contained in static HTML files in the <tt>public</tt> folder, in <tt>404.html</tt> and <tt>500.html</tt> respectively. You can customize these files to add some extra information and layout, but remember that they are static; i.e. you can&#8217;t use RHTML or layouts in them, just plain HTML.</p></div>
<h3 id="_tt_rescue_from_tt">13.2. <tt>rescue_from</tt></h3>
<div class="para"><p>If you want to do something a bit more elaborate when catching errors, you can use <tt>rescue_from</tt>, which handles exceptions of a certain type (or multiple types) in an entire controller and its subclasses. When an exception occurs which is caught by a <tt>rescue_from</tt> directive, the exception object is passed to the handler. The handler can be a method or a Proc object passed to the <tt>:with</tt> option. You can also use a block directly instead of an explicit Proc object.</p></div>
<div class="para"><p>Here's how you can use <tt>rescue_from</tt> to intercept all ActiveRecord::RecordNotFound errors and do something with them.</p></div>
<div class="paragraph"><p>If you want to do something a bit more elaborate when catching errors, you can use <tt>rescue_from</tt>, which handles exceptions of a certain type (or multiple types) in an entire controller and its subclasses. When an exception occurs which is caught by a <tt>rescue_from</tt> directive, the exception object is passed to the handler. The handler can be a method or a Proc object passed to the <tt>:with</tt> option. You can also use a block directly instead of an explicit Proc object.</p></div>
<div class="paragraph"><p>Here&#8217;s how you can use <tt>rescue_from</tt> to intercept all ActiveRecord::RecordNotFound errors and do something with them.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1203,9 +1171,8 @@ private
render <span style="color: #990000">:</span>text <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"404 Not Found"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>status <span style="color: #990000">=&gt;</span> <span style="color: #993399">404</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>Of course, this example is anything but elaborate and doesn't improve on the default exception handling at all, but once you can catch all those exceptions you're free to do whatever you want with them. For example, you could create custom exception classes that will be thrown when a user doesn't have access to a certain section of your application:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Of course, this example is anything but elaborate and doesn&#8217;t improve on the default exception handling at all, but once you can catch all those exceptions you&#8217;re free to do whatever you want with them. For example, you could create custom exception classes that will be thrown when a user doesn&#8217;t have access to a certain section of your application:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1241,21 +1208,20 @@ private
<span style="font-weight: bold"><span style="color: #0000FF">raise</span></span> User<span style="color: #990000">::</span>NotAuthorized <span style="font-weight: bold"><span style="color: #0000FF">unless</span></span> current_user<span style="color: #990000">.</span>admin?
<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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
<td class="content">Certain exceptions are only rescuable from the ApplicationController class, as they are raised before the controller gets initialized and the action gets executed. See Pratik Naik's <a href="http://m.onkey.org/2008/7/20/rescue-from-dispatching">article</a> on the subject for more information.</td>
<td class="content">Certain exceptions are only rescuable from the ApplicationController class, as they are raised before the controller gets initialized and the action gets executed. See Pratik Naik&#8217;s <a href="http://m.onkey.org/2008/7/20/rescue-from-dispatching">article</a> on the subject for more information.</td>
</tr></table>
</div>
</div>
<h2 id="_changelog">14. Changelog</h2>
<div class="sectionbody">
<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/17">Lighthouse ticket</a></p></div>
<div class="ilist"><ul>
<div class="paragraph"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/17">Lighthouse ticket</a></p></div>
<div class="ulist"><ul>
<li>
<p>
November 4, 2008: First release version by Tore Darrell

View File

@@ -323,9 +323,9 @@ ul#navMain {
<h1>Active Record Validations and Callbacks</h1>
<div id="preamble">
<div class="sectionbody">
<div class="para"><p>This guide teaches you how to work with the lifecycle of your Active Record objects. More precisely, you will learn how to validate the state of your objects before they go into the database and also how to teach them to perform custom operations at certain points of their lifecycles.</p></div>
<div class="para"><p>After reading this guide and trying out the presented concepts, we hope that you'll be able to:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>This guide teaches you how to work with the lifecycle of your Active Record objects. More precisely, you will learn how to validate the state of your objects before they go into the database and also how to teach them to perform custom operations at certain points of their lifecycles.</p></div>
<div class="paragraph"><p>After reading this guide and trying out the presented concepts, we hope that you&#8217;ll be able to:</p></div>
<div class="ulist"><ul>
<li>
<p>
Correctly use all the built-in Active Record validation helpers
@@ -361,9 +361,9 @@ Create Observers - classes with callback methods specific for each of your model
</div>
<h2 id="_motivations_to_validate_your_active_record_objects">1. Motivations to validate your Active Record objects</h2>
<div class="sectionbody">
<div class="para"><p>The main reason for validating your objects before they get into the database is to ensure that only valid data is recorded. It's important to be sure that an email address column only contains valid email addresses, or that the customer's name column will never be empty. Constraints like that keep your database organized and helps your application to work properly.</p></div>
<div class="para"><p>There are several ways to validate the data that goes to the database, like using database native constraints, implementing validations only at the client side or implementing them directly into your models. Each one has pros and cons:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>The main reason for validating your objects before they get into the database is to ensure that only valid data is recorded. It&#8217;s important to be sure that an email address column only contains valid email addresses, or that the customer&#8217;s name column will never be empty. Constraints like that keep your database organized and helps your application to work properly.</p></div>
<div class="paragraph"><p>There are several ways to validate the data that goes to the database, like using database native constraints, implementing validations only at the client side or implementing them directly into your models. Each one has pros and cons:</p></div>
<div class="ulist"><ul>
<li>
<p>
Using database constraints and/or stored procedures makes the validation mechanisms database-dependent and may turn your application into a hard to test and mantain beast. However, if your database is used by other applications, it may be a good idea to use some constraints also at the database level.
@@ -371,12 +371,12 @@ Using database constraints and/or stored procedures makes the validation mechani
</li>
<li>
<p>
Implementing validations only at the client side can be problematic, specially with web-based applications. Usually this kind of validation is done using javascript, which may be turned off in the user's browser, leading to invalid data getting inside your database. However, if combined with server side validation, client side validation may be useful, since the user can have a faster feedback from the application when trying to save invalid data.
Implementing validations only at the client side can be problematic, specially with web-based applications. Usually this kind of validation is done using javascript, which may be turned off in the user&#8217;s browser, leading to invalid data getting inside your database. However, if combined with server side validation, client side validation may be useful, since the user can have a faster feedback from the application when trying to save invalid data.
</p>
</li>
<li>
<p>
Using validation directly into your Active Record classes ensures that only valid data gets recorded, while still keeping the validation code in the right place, avoiding breaking the MVC pattern. Since the validation happens on the server side, the user cannot disable it, so it's also safer. It may be a hard and tedious work to implement some of the logic involved in your models' validations, but fear not: Active Record gives you the hability to easily create validations, using several built-in helpers while still allowing you to create your own validation methods.
Using validation directly into your Active Record classes ensures that only valid data gets recorded, while still keeping the validation code in the right place, avoiding breaking the MVC pattern. Since the validation happens on the server side, the user cannot disable it, so it&#8217;s also safer. It may be a hard and tedious work to implement some of the logic involved in your models' validations, but fear not: Active Record gives you the hability to easily create validations, using several built-in helpers while still allowing you to create your own validation methods.
</p>
</li>
</ul></div>
@@ -384,16 +384,15 @@ Using validation directly into your Active Record classes ensures that only vali
<h2 id="_how_it_works">2. How it works</h2>
<div class="sectionbody">
<h3 id="_when_does_validation_happens">2.1. When does validation happens?</h3>
<div class="para"><p>There are two kinds of Active Record objects: those that correspond to a row inside your database and those who do not. When you create a fresh object, using the <tt>new</tt> method, that object does not belong to the database yet. Once you call <tt>save</tt> upon that object it'll be recorded to it's table. Active Record uses the <tt>new_record?</tt> instance method to discover if an object is already in the database or not. Consider the following simple and very creative Active Record class:</p></div>
<div class="paragraph"><p>There are two kinds of Active Record objects: those that correspond to a row inside your database and those who do not. When you create a fresh object, using the <tt>new</tt> method, that object does not belong to the database yet. Once you call <tt>save</tt> upon that object it&#8217;ll be recorded to it&#8217;s table. Active Record uses the <tt>new_record?</tt> instance method to discover if an object is already in the database or not. Consider the following simple and very creative Active Record class:</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> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>We can see how it works by looking at the following script/console output:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>We can see how it works by looking at the following script/console output:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&gt;&gt; p = Person.new(:name =&gt; "John Doe", :birthdate =&gt; Date.parse("09/03/1979"))
@@ -405,7 +404,7 @@ http://www.gnu.org/software/src-highlite -->
&gt;&gt; p.new_record?
=&gt; false</tt></pre>
</div></div>
<div class="para"><p>Saving new records means sending an SQL insert operation to the database, while saving existing records (by calling either <tt>save</tt> or <tt>update_attributes</tt>) will result in a SQL update operation. Active Record will use these facts to perform validations upon your objects, avoiding then to be recorded to the database if their inner state is invalid in some way. You can specify validations that will be beformed every time a object is saved, just when you're creating a new record or when you're updating an existing one.</p></div>
<div class="paragraph"><p>Saving new records means sending an SQL insert operation to the database, while saving existing records (by calling either <tt>save</tt> or <tt>update_attributes</tt>) will result in a SQL update operation. Active Record will use these facts to perform validations upon your objects, avoiding then to be recorded to the database if their inner state is invalid in some way. You can specify validations that will be beformed every time a object is saved, just when you&#8217;re creating a new record or when you&#8217;re updating an existing one.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -415,15 +414,15 @@ http://www.gnu.org/software/src-highlite -->
</tr></table>
</div>
<h3 id="_the_meaning_of_em_valid_em">2.2. The meaning of <em>valid</em></h3>
<div class="para"><p>For verifying if an object is valid, Active Record uses the <tt>valid?</tt> method, which basically looks inside the object to see if it has any validation errors. These errors live in a collection that can be accessed through the <tt>errors</tt> instance method. The proccess is really simple: If the <tt>errors</tt> method returns an empty collection, the object is valid and can be saved. Each time a validation fails, an error message is added to the <tt>errors</tt> collection.</p></div>
<div class="paragraph"><p>For verifying if an object is valid, Active Record uses the <tt>valid?</tt> method, which basically looks inside the object to see if it has any validation errors. These errors live in a collection that can be accessed through the <tt>errors</tt> instance method. The proccess is really simple: If the <tt>errors</tt> method returns an empty collection, the object is valid and can be saved. Each time a validation fails, an error message is added to the <tt>errors</tt> collection.</p></div>
</div>
<h2 id="_the_declarative_validation_helpers">3. The declarative validation helpers</h2>
<div class="sectionbody">
<div class="para"><p>Active Record offers many pre-defined validation helpers that you can use directly inside your class definitions. These helpers create validations rules that are commonly used in most of the applications that you'll write, so you don't need to recreate it everytime, avoiding code duplication, keeping everything organized and boosting your productivity. Everytime a validation fails, an error message is added to the object's <tt>errors</tt> collection, this message being associated with the field being validated.</p></div>
<div class="para"><p>Each helper accepts an arbitrary number of attributes, received as symbols, so with a single line of code you can add the same kind of validation to several attributes.</p></div>
<div class="para"><p>All these helpers accept the <tt>:on</tt> and <tt>:message</tt> options, which define when the validation should be applied and what message should be added to the <tt>errors</tt> collection when it fails, respectively. The <tt>:on</tt> option takes one the values <tt>:save</tt> (it's the default), <tt>:create</tt> or <tt>:update</tt>. There is a default error message for each one of the validation helpers. These messages are used when the <tt>:message</tt> option isn't used. Let's take a look at each one of the available helpers, listed in alphabetic order.</p></div>
<div class="paragraph"><p>Active Record offers many pre-defined validation helpers that you can use directly inside your class definitions. These helpers create validations rules that are commonly used in most of the applications that you&#8217;ll write, so you don&#8217;t need to recreate it everytime, avoiding code duplication, keeping everything organized and boosting your productivity. Everytime a validation fails, an error message is added to the object&#8217;s <tt>errors</tt> collection, this message being associated with the field being validated.</p></div>
<div class="paragraph"><p>Each helper accepts an arbitrary number of attributes, received as symbols, so with a single line of code you can add the same kind of validation to several attributes.</p></div>
<div class="paragraph"><p>All these helpers accept the <tt>:on</tt> and <tt>:message</tt> options, which define when the validation should be applied and what message should be added to the <tt>errors</tt> collection when it fails, respectively. The <tt>:on</tt> option takes one the values <tt>:save</tt> (it&#8217;s the default), <tt>:create</tt> or <tt>:update</tt>. There is a default error message for each one of the validation helpers. These messages are used when the <tt>:message</tt> option isn&#8217;t used. Let&#8217;s take a look at each one of the available helpers, listed in alphabetic order.</p></div>
<h3 id="_the_tt_validates_acceptance_of_tt_helper">3.1. The <tt>validates_acceptance_of</tt> helper</h3>
<div class="para"><p>Validates that a checkbox has been checked for agreement purposes. It's normally used when the user needs to agree with your application's terms of service, confirm reading some clauses or any similar concept. This validation is very specific to web applications and actually this <em>acceptance</em> does not need to be recorded anywhere in your database (if you don't have a field for it, the helper will just create a virtual attribute).</p></div>
<div class="paragraph"><p>Validates that a checkbox has been checked for agreement purposes. It&#8217;s normally used when the user needs to agree with your application&#8217;s terms of service, confirm reading some clauses or any similar concept. This validation is very specific to web applications and actually this <em>acceptance</em> does not need to be recorded anywhere in your database (if you don&#8217;t have a field for it, the helper will just create a virtual attribute).</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -431,10 +430,9 @@ 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> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_acceptance_of <span style="color: #990000">:</span>terms_of_service
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The default error message for <tt>validates_acceptance_of</tt> is "<em>must be accepted</em>"</p></div>
<div class="para"><p><tt>validates_acceptance_of</tt> can receive an <tt>:accept</tt> option, which determines the value that will be considered acceptance. It defaults to "1", but you can change it.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The default error message for <tt>validates_acceptance_of</tt> is "<em>must be accepted</em>"</p></div>
<div class="paragraph"><p><tt>validates_acceptance_of</tt> can receive an <tt>:accept</tt> option, which determines the value that will be considered acceptance. It defaults to "1", but you can change it.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -442,10 +440,9 @@ 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> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_acceptance_of <span style="color: #990000">:</span>terms_of_service<span style="color: #990000">,</span> <span style="color: #990000">:</span>accept <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'yes'</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<h3 id="_the_tt_validates_associated_tt_helper">3.2. The <tt>validates_associated</tt> helper</h3>
<div class="para"><p>You should use this helper when your model has associations with other models and they also need to be validated. When you try to save your object, <tt>valid?</tt> will be called upon each one of the associated objects.</p></div>
<div class="paragraph"><p>You should use this helper when your model has associations with other models and they also need to be validated. When you try to save your object, <tt>valid?</tt> will be called upon each one of the associated objects.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -454,9 +451,8 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Library <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
has_many <span style="color: #990000">:</span>books
validates_associated <span style="color: #990000">:</span>books
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>This validation will work with all the association types.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This validation will work with all the association types.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -465,9 +461,9 @@ http://www.gnu.org/software/src-highlite -->
<td class="content">Pay attention not to use <tt>validates_associated</tt> on both ends of your associations, because this will lead to several recursive calls and blow up the method calls' stack.</td>
</tr></table>
</div>
<div class="para"><p>The default error message for <tt>validates_associated</tt> is "<em>is invalid</em>". Note that the errors for each failed validation in the associated objects will be set there and not in this model.</p></div>
<div class="paragraph"><p>The default error message for <tt>validates_associated</tt> is "<em>is invalid</em>". Note that the errors for each failed validation in the associated objects will be set there and not in this model.</p></div>
<h3 id="_the_tt_validates_confirmation_of_tt_helper">3.3. The <tt>validates_confirmation_of</tt> helper</h3>
<div class="para"><p>You should use this helper when you have two text fields that should receive exactly the same content, like when you want to confirm an email address or password. This validation creates a virtual attribute, using the name of the field that has to be confirmed with <em>_confirmation</em> appended.</p></div>
<div class="paragraph"><p>You should use this helper when you have two text fields that should receive exactly the same content, like when you want to confirm an email address or password. This validation creates a virtual attribute, using the name of the field that has to be confirmed with <em>_confirmation</em> appended.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -475,9 +471,8 @@ 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> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_confirmation_of <span style="color: #990000">:</span>email
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>In your view template you could use something like</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>In your view template you could use something like</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= text_field :person, :email %&gt;
@@ -488,7 +483,7 @@ http://www.gnu.org/software/src-highlite -->
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
<td class="content">This check is performed only if <tt>email_confirmation</tt> is not nil, and by default only on save. To require confirmation, make sure to add a presence check for the confirmation attribute (we'll take a look at <tt>validates_presence_of</tt> later on this guide):</td>
<td class="content">This check is performed only if <tt>email_confirmation</tt> is not nil, and by default only on save. To require confirmation, make sure to add a presence check for the confirmation attribute (we&#8217;ll take a look at <tt>validates_presence_of</tt> later on this guide):</td>
</tr></table>
</div>
<div class="listingblock">
@@ -499,11 +494,10 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_confirmation_of <span style="color: #990000">:</span>email
validates_presence_of <span style="color: #990000">:</span>email_confirmation
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The default error message for <tt>validates_confirmation_of</tt> is "<em>doesn't match confirmation</em>"</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The default error message for <tt>validates_confirmation_of</tt> is "<em>doesn&#8217;t match confirmation</em>"</p></div>
<h3 id="_the_tt_validates_each_tt_helper">3.4. The <tt>validates_each</tt> helper</h3>
<div class="para"><p>This helper validates attributes against a block. It doesn't have a predefined validation function. You should create one using a block, and every attribute passed to <tt>validates_each</tt> will be tested against it. In the following example, we don't want names and surnames to begin with lower case.</p></div>
<div class="paragraph"><p>This helper validates attributes against a block. It doesn&#8217;t have a predefined validation function. You should create one using a block, and every attribute passed to <tt>validates_each</tt> will be tested against it. In the following example, we don&#8217;t want names and surnames to begin with lower case.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -513,11 +507,10 @@ http://www.gnu.org/software/src-highlite -->
validates_each <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>surname <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>model<span style="color: #990000">,</span> attr<span style="color: #990000">,</span> value<span style="color: #990000">|</span>
model<span style="color: #990000">.</span>errors<span style="color: #990000">.</span>add<span style="color: #990000">(</span>attr<span style="color: #990000">,</span> <span style="color: #FF0000">'Must start with upper case'</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> value <span style="color: #990000">=~</span> <span style="color: #FF6600">/^[a-z]/</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>The block receives the model, the attribute's name and the attribute's value. If your validation fails, you can add an error message to the model, therefore making it invalid.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The block receives the model, the attribute&#8217;s name and the attribute&#8217;s value. If your validation fails, you can add an error message to the model, therefore making it invalid.</p></div>
<h3 id="_the_tt_validates_exclusion_of_tt_helper">3.5. The <tt>validates_exclusion_of</tt> helper</h3>
<div class="para"><p>This helper validates that the attributes' values are not included in a given set. In fact, this set can be any enumerable object.</p></div>
<div class="paragraph"><p>This helper validates that the attributes' values are not included in a given set. In fact, this set can be any enumerable object.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -526,12 +519,11 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> MovieFile <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_exclusion_of <span style="color: #990000">:</span>format<span style="color: #990000">,</span> <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">in</span></span> <span style="color: #990000">=&gt;</span> <span style="color: #990000">%</span>w<span style="color: #990000">(</span>mov avi<span style="color: #990000">),</span>
<span style="color: #990000">:</span>message <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"Extension %s is not allowed"</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The <tt>validates_exclusion_of</tt> helper has an option <tt>:in</tt> that receives the set of values that will not be accepted for the validated attributes. The <tt>:in</tt> option has an alias called <tt>:within</tt> that you can use for the same purpose, if you'd like to. In the previous example we used the <tt>:message</tt> option to show how we can personalize it with the current attribute's value, through the <tt>%s</tt> format mask.</p></div>
<div class="para"><p>The default error message for <tt>validates_exclusion_of</tt> is "<em>is not included in the list</em>".</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The <tt>validates_exclusion_of</tt> helper has an option <tt>:in</tt> that receives the set of values that will not be accepted for the validated attributes. The <tt>:in</tt> option has an alias called <tt>:within</tt> that you can use for the same purpose, if you&#8217;d like to. In the previous example we used the <tt>:message</tt> option to show how we can personalize it with the current attribute&#8217;s value, through the <tt>%s</tt> format mask.</p></div>
<div class="paragraph"><p>The default error message for <tt>validates_exclusion_of</tt> is "<em>is not included in the list</em>".</p></div>
<h3 id="_the_tt_validates_format_of_tt_helper">3.6. The <tt>validates_format_of</tt> helper</h3>
<div class="para"><p>This helper validates the attributes's values by testing if they match a given pattern. This pattern must be specified using a Ruby regular expression, which must be passed through the <tt>:with</tt> option.</p></div>
<div class="paragraph"><p>This helper validates the attributes&#8217;s values by testing if they match a given pattern. This pattern must be specified using a Ruby regular expression, which must be passed through the <tt>:with</tt> option.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -540,11 +532,10 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Product <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_format_of <span style="color: #990000">:</span>description<span style="color: #990000">,</span> <span style="color: #990000">:</span>with <span style="color: #990000">=&gt;</span> <span style="color: #FF6600">/^[a-zA-Z]+$/</span><span style="color: #990000">,</span>
<span style="color: #990000">:</span>message <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"Only letters allowed"</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The default error message for <tt>validates_format_of</tt> is "<em>is invalid</em>".</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The default error message for <tt>validates_format_of</tt> is "<em>is invalid</em>".</p></div>
<h3 id="_the_tt_validates_inclusion_of_tt_helper">3.7. The <tt>validates_inclusion_of</tt> helper</h3>
<div class="para"><p>This helper validates that the attributes' values are included in a given set. In fact, this set can be any enumerable object.</p></div>
<div class="paragraph"><p>This helper validates that the attributes' values are included in a given set. In fact, this set can be any enumerable object.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -553,12 +544,11 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Coffee <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_inclusion_of <span style="color: #990000">:</span>size<span style="color: #990000">,</span> <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">in</span></span> <span style="color: #990000">=&gt;</span> <span style="color: #990000">%</span>w<span style="color: #990000">(</span>small medium large<span style="color: #990000">),</span>
<span style="color: #990000">:</span>message <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"%s is not a valid size"</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The <tt>validates_inclusion_of</tt> helper has an option <tt>:in</tt> that receives the set of values that will be accepted. The <tt>:in</tt> option has an alias called <tt>:within</tt> that you can use for the same purpose, if you'd like to. In the previous example we used the <tt>:message</tt> option to show how we can personalize it with the current attribute's value, through the <tt>%s</tt> format mask.</p></div>
<div class="para"><p>The default error message for <tt>validates_inclusion_of</tt> is "<em>is not included in the list</em>".</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The <tt>validates_inclusion_of</tt> helper has an option <tt>:in</tt> that receives the set of values that will be accepted. The <tt>:in</tt> option has an alias called <tt>:within</tt> that you can use for the same purpose, if you&#8217;d like to. In the previous example we used the <tt>:message</tt> option to show how we can personalize it with the current attribute&#8217;s value, through the <tt>%s</tt> format mask.</p></div>
<div class="paragraph"><p>The default error message for <tt>validates_inclusion_of</tt> is "<em>is not included in the list</em>".</p></div>
<h3 id="_the_tt_validates_length_of_tt_helper">3.8. The <tt>validates_length_of</tt> helper</h3>
<div class="para"><p>This helper validates the length of your attribute's value. It can receive a variety of different options, so you can specify length contraints in different ways.</p></div>
<div class="paragraph"><p>This helper validates the length of your attribute&#8217;s value. It can receive a variety of different options, so you can specify length contraints in different ways.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -569,10 +559,9 @@ http://www.gnu.org/software/src-highlite -->
validates_length_of <span style="color: #990000">:</span>bio<span style="color: #990000">,</span> <span style="color: #990000">:</span>maximum <span style="color: #990000">=&gt;</span> <span style="color: #993399">500</span>
validates_length_of <span style="color: #990000">:</span>password<span style="color: #990000">,</span> <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">in</span></span> <span style="color: #990000">=&gt;</span> <span style="color: #993399">6</span><span style="color: #990000">..</span><span style="color: #993399">20</span>
validates_length_of <span style="color: #990000">:</span>registration_number<span style="color: #990000">,</span> <span style="color: #990000">:</span>is <span style="color: #990000">=&gt;</span> <span style="color: #993399">6</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The possible length constraint options are:</p></div>
<div class="ilist"><ul>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The possible length constraint options are:</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>:minimum</tt> - The attribute cannot have less than the specified length.
@@ -594,7 +583,7 @@ http://www.gnu.org/software/src-highlite -->
</p>
</li>
</ul></div>
<div class="para"><p>The default error messages depend on the type of length validation being performed. You can personalize these messages, using the <tt>:wrong_length</tt>, <tt>:too_long</tt> and <tt>:too_short</tt> options and the <tt>%d</tt> format mask as a placeholder for the number corresponding to the length contraint being used. You can still use the <tt>:message</tt> option to specify an error message.</p></div>
<div class="paragraph"><p>The default error messages depend on the type of length validation being performed. You can personalize these messages, using the <tt>:wrong_length</tt>, <tt>:too_long</tt> and <tt>:too_short</tt> options and the <tt>%d</tt> format mask as a placeholder for the number corresponding to the length contraint being used. You can still use the <tt>:message</tt> option to specify an error message.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -602,12 +591,11 @@ 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> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_length_of <span style="color: #990000">:</span>bio<span style="color: #990000">,</span> <span style="color: #990000">:</span>too_long <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"you're writing too much. %d characters is the maximum allowed."</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>This helper has an alias called <tt>validates_size_of</tt>, it's the same helper with a different name. You can use it if you'd like to.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This helper has an alias called <tt>validates_size_of</tt>, it&#8217;s the same helper with a different name. You can use it if you&#8217;d like to.</p></div>
<h3 id="_the_tt_validates_numericality_of_tt_helper">3.9. The <tt>validates_numericality_of</tt> helper</h3>
<div class="para"><p>This helper validates that your attributes have only numeric values. By default, it will match an optional sign followed by a integral or floating point number. Using the <tt>:integer_only</tt> option set to true, you can specify that only integral numbers are allowed.</p></div>
<div class="para"><p>If you use <tt>:integer_only</tt> set to <tt>true</tt>, then it will use the <tt><span>/\A[+\-]?\d+\Z/</span></tt> regular expression to validate the attribute's value. Otherwise, it will try to convert the value using <tt>Kernel.Float</tt>.</p></div>
<div class="paragraph"><p>This helper validates that your attributes have only numeric values. By default, it will match an optional sign followed by a integral or floating point number. Using the <tt>:integer_only</tt> option set to true, you can specify that only integral numbers are allowed.</p></div>
<div class="paragraph"><p>If you use <tt>:integer_only</tt> set to <tt>true</tt>, then it will use the <tt>/\A[+\-]?\d+\Z/+ regular expression to validate the attribute&#8217;s value. Otherwise, it will try to convert the value using +Kernel.Float</tt>.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -616,11 +604,10 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Player <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_numericality_of <span style="color: #990000">:</span>points
validates_numericality_of <span style="color: #990000">:</span>games_played<span style="color: #990000">,</span> <span style="color: #990000">:</span>integer_only <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The default error message for <tt>validates_numericality_of</tt> is "<em>is not a number</em>".</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The default error message for <tt>validates_numericality_of</tt> is "<em>is not a number</em>".</p></div>
<h3 id="_the_tt_validates_presence_of_tt_helper">3.10. The <tt>validates_presence_of</tt> helper</h3>
<div class="para"><p>This helper validates that the attributes are not empty. It uses the <tt>blank?</tt> method to check if the value is either <tt>nil</tt> or an empty string (if the string has only spaces, it will still be considered empty).</p></div>
<div class="paragraph"><p>This helper validates that the attributes are not empty. It uses the <tt>blank?</tt> method to check if the value is either <tt>nil</tt> or an empty string (if the string has only spaces, it will still be considered empty).</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -628,14 +615,13 @@ 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> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_presence_of <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>login<span style="color: #990000">,</span> <span style="color: #990000">:</span>email
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
<td class="content">If you want to be sure that an association is present, you'll need to test if the foreign key used to map the association is present, and not the associated object itself.</td>
<td class="content">If you want to be sure that an association is present, you&#8217;ll need to test if the foreign key used to map the association is present, and not the associated object itself.</td>
</tr></table>
</div>
<div class="listingblock">
@@ -646,19 +632,18 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> LineItem <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
belongs_to <span style="color: #990000">:</span>order
validates_presence_of <span style="color: #990000">:</span>order_id
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
<td class="content">If you want to validate the presence of a boolean field (where the real values are true and false), you will want to use validates_inclusion_of :field_name, :in &#8658; [true, false] This is due to the way Object#blank? handles boolean values. false.blank? # &#8658; true</td>
<td class="content">If you want to validate the presence of a boolean field (where the real values are true and false), you will want to use validates_inclusion_of :field_name, :in =&gt; [true, false] This is due to the way Object#blank? handles boolean values. false.blank? # =&gt; true</td>
</tr></table>
</div>
<div class="para"><p>The default error message for <tt>validates_presence_of</tt> is "<em>can't be empty</em>".</p></div>
<div class="paragraph"><p>The default error message for <tt>validates_presence_of</tt> is "<em>can&#8217;t be empty</em>".</p></div>
<h3 id="_the_tt_validates_uniqueness_of_tt_helper">3.11. The <tt>validates_uniqueness_of</tt> helper</h3>
<div class="para"><p>This helper validates that the attribute's value is unique right before the object gets saved. It does not create a uniqueness constraint directly into your database, so it may happen that two different database connections create two records with the same value for a column that you wish were unique. To avoid that, you must create an unique index in your database.</p></div>
<div class="paragraph"><p>This helper validates that the attribute&#8217;s value is unique right before the object gets saved. It does not create a uniqueness constraint directly into your database, so it may happen that two different database connections create two records with the same value for a column that you wish were unique. To avoid that, you must create an unique index in your database.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -666,10 +651,9 @@ 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> Account <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_uniqueness_of <span style="color: #990000">:</span>email
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The validation happens by performing a SQL query into the model's table, searching for a record where the attribute that must be validated is equal to the value in the object being validated.</p></div>
<div class="para"><p>There is a <tt>:scope</tt> option that you can use to specify other attributes that must be used to define uniqueness:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The validation happens by performing a SQL query into the model&#8217;s table, searching for a record where the attribute that must be validated is equal to the value in the object being validated.</p></div>
<div class="paragraph"><p>There is a <tt>:scope</tt> option that you can use to specify other attributes that must be used to define uniqueness:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -678,9 +662,8 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Holiday <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_uniqueness_of <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>scope <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>year<span style="color: #990000">,</span>
<span style="color: #990000">:</span>message <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"Should happen once per year"</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>There is also a <tt>:case_sensitive</tt> option that you can use to define if the uniqueness contraint will be case sensitive or not. This option defaults to true.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>There is also a <tt>:case_sensitive</tt> option that you can use to define if the uniqueness contraint will be case sensitive or not. This option defaults to true.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -688,15 +671,14 @@ 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> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_uniqueness_of <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>case_sensitive <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The default error message for <tt>validates_uniqueness_of</tt> is "<em>has already been taken</em>".</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The default error message for <tt>validates_uniqueness_of</tt> is "<em>has already been taken</em>".</p></div>
</div>
<h2 id="_common_validation_options">4. Common validation options</h2>
<div class="sectionbody">
<div class="para"><p>There are some common options that all the validation helpers can use. Here they are, except for the <tt>:if</tt> and <tt>:unless</tt> options, which we'll cover right at the next topic.</p></div>
<div class="paragraph"><p>There are some common options that all the validation helpers can use. Here they are, except for the <tt>:if</tt> and <tt>:unless</tt> options, which we&#8217;ll cover right at the next topic.</p></div>
<h3 id="_the_tt_allow_nil_tt_option">4.1. The <tt>:allow_nil</tt> option</h3>
<div class="para"><p>You may use the <tt>:allow_nil</tt> option everytime you want to trigger a validation only if the value being validated is not <tt>nil</tt>. You may be asking yourself if it makes any sense to use <tt>:allow_nil</tt> and <tt>validates_presence_of</tt> together. Well, it does. Remember, validation will be skipped only for <tt>nil</tt> attributes, but empty strings are not considered <tt>nil</tt>.</p></div>
<div class="paragraph"><p>You may use the <tt>:allow_nil</tt> option everytime you want to trigger a validation only if the value being validated is not <tt>nil</tt>. You may be asking yourself if it makes any sense to use <tt>:allow_nil</tt> and <tt>validates_presence_of</tt> together. Well, it does. Remember, validation will be skipped only for <tt>nil</tt> attributes, but empty strings are not considered <tt>nil</tt>.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -705,12 +687,11 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Coffee <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_inclusion_of <span style="color: #990000">:</span>size<span style="color: #990000">,</span> <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">in</span></span> <span style="color: #990000">=&gt;</span> <span style="color: #990000">%</span>w<span style="color: #990000">(</span>small medium large<span style="color: #990000">),</span>
<span style="color: #990000">:</span>message <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"%s is not a valid size"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>allow_nil <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<h3 id="_the_tt_message_tt_option">4.2. The <tt>:message</tt> option</h3>
<div class="para"><p>As stated before, the <tt>:message</tt> option lets you specify the message that will be added to the <tt>errors</tt> collection when validation fails. When this option is not used, Active Record will use the respective default error message for each validation helper.</p></div>
<div class="paragraph"><p>As stated before, the <tt>:message</tt> option lets you specify the message that will be added to the <tt>errors</tt> collection when validation fails. When this option is not used, Active Record will use the respective default error message for each validation helper.</p></div>
<h3 id="_the_tt_on_tt_option">4.3. The <tt>:on</tt> option</h3>
<div class="para"><p>As stated before, the <tt>:on</tt> option lets you specify when the validation should happen. The default behaviour for all the built-in validation helpers is to be ran on save (both when you're creating a new record and when you're updating it). If you want to change it, you can use <tt>:on =<span>&gt;</span> :create</tt> to run the validation only when a new record is created or <tt>:on =<span>&gt;</span> :update</tt> to run the validation only when a record is updated.</p></div>
<div class="paragraph"><p>As stated before, the <tt>:on</tt> option lets you specify when the validation should happen. The default behaviour for all the built-in validation helpers is to be ran on save (both when you&#8217;re creating a new record and when you&#8217;re updating it). If you want to change it, you can use <tt>:on =&gt; :create</tt> to run the validation only when a new record is created or <tt>:on =&gt; :update</tt> to run the validation only when a record is updated.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -725,14 +706,13 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-style: italic"><span style="color: #9A1900"># =&gt; the default</span></span>
validates_presence_of <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>on <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>save
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
</div>
<h2 id="_conditional_validation">5. Conditional validation</h2>
<div class="sectionbody">
<div class="para"><p>Sometimes it will make sense to validate an object just when a given predicate is satisfied. You can do that by using the <tt>:if</tt> and <tt>:unless</tt> options, which can take a symbol, a string or a Ruby Proc. You may use the <tt>:if</tt> option when you want to specify when the validation <strong>should</strong> happen. If you want to specify when the validation <strong>should not</strong> happen, then you may use the <tt>:unless</tt> option.</p></div>
<div class="paragraph"><p>Sometimes it will make sense to validate an object just when a given predicate is satisfied. You can do that by using the <tt>:if</tt> and <tt>:unless</tt> options, which can take a symbol, a string or a Ruby Proc. You may use the <tt>:if</tt> option when you want to specify when the validation <strong>should</strong> happen. If you want to specify when the validation <strong>should not</strong> happen, then you may use the <tt>:unless</tt> option.</p></div>
<h3 id="_using_a_symbol_with_the_tt_if_tt_and_tt_unless_tt_options">5.1. Using a symbol with the <tt>:if</tt> and <tt>:unless</tt> options</h3>
<div class="para"><p>You can associated the <tt>:if</tt> and <tt>:unless</tt> options with a symbol corresponding to the name of a method that will get called right before validation happens. This is the most commonly used option.</p></div>
<div class="paragraph"><p>You can associated the <tt>:if</tt> and <tt>:unless</tt> options with a symbol corresponding to the name of a method that will get called right before validation happens. This is the most commonly used option.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -744,10 +724,9 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> paid_with_card?
payment_type <span style="color: #990000">==</span> <span style="color: #FF0000">"card"</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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<h3 id="_using_a_string_with_the_tt_if_tt_and_tt_unless_tt_options">5.2. Using a string with the <tt>:if</tt> and <tt>:unless</tt> options</h3>
<div class="para"><p>You can also use a string that will be evaluated using <tt>:eval</tt> and needs to contain valid Ruby code. You should use this option only when the string represents a really short condition.</p></div>
<div class="paragraph"><p>You can also use a string that will be evaluated using <tt>:eval</tt> and needs to contain valid Ruby code. You should use this option only when the string represents a really short condition.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -755,10 +734,9 @@ 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> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_presence_of <span style="color: #990000">:</span>surname<span style="color: #990000">,</span> <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"name.nil?"</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<h3 id="_using_a_proc_object_with_the_tt_if_tt_and_tt_unless_tt_options">5.3. Using a Proc object with the <tt>:if</tt> and :<tt>unless</tt> options</h3>
<div class="para"><p>Finally, it's possible to associate <tt>:if</tt> and <tt>:unless</tt> with a Ruby Proc object which will be called. Using a Proc object can give you the hability to write a condition that will be executed only when the validation happens and not when your code is loaded by the Ruby interpreter. This option is best suited when writing short validation methods, usually one-liners.</p></div>
<div class="paragraph"><p>Finally, it&#8217;s possible to associate <tt>:if</tt> and <tt>:unless</tt> with a Ruby Proc object which will be called. Using a Proc object can give you the hability to write a condition that will be executed only when the validation happens and not when your code is loaded by the Ruby interpreter. This option is best suited when writing short validation methods, usually one-liners.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -767,12 +745,11 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Account <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_confirmation_of <span style="color: #990000">:</span>password<span style="color: #990000">,</span>
<span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">unless</span></span> <span style="color: #990000">=&gt;</span> Proc<span style="color: #990000">.</span>new <span style="color: #FF0000">{</span> <span style="color: #990000">|</span>a<span style="color: #990000">|</span> a<span style="color: #990000">.</span>password<span style="color: #990000">.</span>blank? <span style="color: #FF0000">}</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
</div>
<h2 id="_writing_your_own_validation_methods">6. Writing your own validation methods</h2>
<div class="sectionbody">
<div class="para"><p>When the built-in validation helpers are not enough for your needs, you can write your own validation methods, by implementing one or more of the <tt>validate</tt>, <tt>validate_on_create</tt> or <tt>validate_on_update</tt> methods. As the names of the methods states, the right method to implement depends on when you want the validations to be ran. The meaning of valid is still the same: to make an object invalid you just need to add a message to it's <tt>errors</tt> collection.</p></div>
<div class="paragraph"><p>When the built-in validation helpers are not enough for your needs, you can write your own validation methods, by implementing one or more of the <tt>validate</tt>, <tt>validate_on_create</tt> or <tt>validate_on_update</tt> methods. As the names of the methods states, the right method to implement depends on when you want the validations to be ran. The meaning of valid is still the same: to make an object invalid you just need to add a message to it&#8217;s <tt>errors</tt> collection.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -783,9 +760,8 @@ http://www.gnu.org/software/src-highlite -->
errors<span style="color: #990000">.</span>add<span style="color: #990000">(:</span>expiration_date<span style="color: #990000">,</span> <span style="color: #FF0000">"can't be in the past"</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">if</span></span>
<span style="color: #990000">!</span>expiration_date<span style="color: #990000">.</span>blank? <span style="font-weight: bold"><span style="color: #0000FF">and</span></span> expiration_date <span style="color: #990000">&lt;</span> Date<span style="color: #990000">.</span>today
<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>If your validation rules are too complicated and you want to break them in small methods, you can implement all of them and call one of <tt>validate</tt>, <tt>validate_on_create</tt> or <tt>validate_on_update</tt> methods, passing it the symbols for the methods' names.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>If your validation rules are too complicated and you want to break them in small methods, you can implement all of them and call one of <tt>validate</tt>, <tt>validate_on_create</tt> or <tt>validate_on_update</tt> methods, passing it the symbols for the methods' names.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -804,16 +780,15 @@ http://www.gnu.org/software/src-highlite -->
errors<span style="color: #990000">.</span>add<span style="color: #990000">(:</span>discount<span style="color: #990000">,</span> <span style="color: #FF0000">"can't be greater than total value"</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">unless</span></span>
discount <span style="color: #990000">&lt;=</span> total_value
<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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
</div>
<h2 id="_using_the_tt_errors_tt_collection">7. Using the <tt>errors</tt> collection</h2>
<div class="sectionbody">
<div class="para"><p>You can do more than just call <tt>valid?</tt> upon your objects based on the existance of the <tt>errors</tt> collection. Here is a list of the other available methods that you can use to manipulate errors or ask for an object's state.</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>You can do more than just call <tt>valid?</tt> upon your objects based on the existance of the <tt>errors</tt> collection. Here is a list of the other available methods that you can use to manipulate errors or ask for an object&#8217;s state.</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>add_to_base</tt> lets you add errors messages that are related to the object's state as a whole, instead of being related to a specific attribute. You can use this method when you want to say that the object is invalid, no matter the values of it's attributes. <tt>add_to_base</tt> receives a string with the message.
<tt>add_to_base</tt> lets you add errors messages that are related to the object&#8217;s state as a whole, instead of being related to a specific attribute. You can use this method when you want to say that the object is invalid, no matter the values of it&#8217;s attributes. <tt>add_to_base</tt> receives a string with the message.
</p>
</li>
</ul></div>
@@ -826,9 +801,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> a_method_used_for_validation_purposes
errors<span style="color: #990000">.</span>add_to_base<span style="color: #990000">(</span><span style="color: #FF0000">"This person is invalid because ..."</span><span style="color: #990000">)</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="ilist"><ul>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="ulist"><ul>
<li>
<p>
<tt>add</tt> lets you manually add messages that are related to particular attributes. When writing those messages, keep in mind that Rails will prepend them with the name of the attribute that holds the error, so write it in a way that makes sense. <tt>add</tt> receives a symbol with the name of the attribute that you want to add the message to and the message itself.
@@ -844,9 +818,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> a_method_used_for_validation_purposes
errors<span style="color: #990000">.</span>add<span style="color: #990000">(:</span>name<span style="color: #990000">,</span> <span style="color: #FF0000">"can't have the characters !@#$%*()_-+="</span><span style="color: #990000">)</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="ilist"><ul>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="ulist"><ul>
<li>
<p>
<tt>invalid?</tt> is used when you want to check if a particular attribute is invalid. It receives a symbol with the name of the attribute that you want to check.
@@ -863,9 +836,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
person <span style="color: #990000">=</span> Person<span style="color: #990000">.</span>new<span style="color: #990000">(:</span>name <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"John Doe"</span><span style="color: #990000">)</span>
person<span style="color: #990000">.</span>invalid?<span style="color: #990000">(:</span>email<span style="color: #990000">)</span> <span style="font-style: italic"><span style="color: #9A1900"># =&gt; true</span></span>
</tt></pre></div></div>
<div class="ilist"><ul>
person<span style="color: #990000">.</span>invalid?<span style="color: #990000">(:</span>email<span style="color: #990000">)</span> <span style="font-style: italic"><span style="color: #9A1900"># =&gt; true</span></span></tt></pre></div></div>
<div class="ulist"><ul>
<li>
<p>
<tt>on</tt> is used when you want to check the error messages for a specific attribute. It will return different kinds of objects depending on the state of the <tt>errors</tt> collection for the given attribute. If there are no errors related to the attribute, <tt>on</tt> will return <tt>nil</tt>. If there is just one errors message for this attribute, <tt>on</tt> will return a string with the message. When <tt>errors</tt> holds two or more error messages for the attribute, <tt>on</tt> will return an array of strings, each one with one error message.
@@ -894,12 +866,11 @@ person<span style="color: #990000">.</span>errors<span style="color: #990000">.<
person <span style="color: #990000">=</span> Person<span style="color: #990000">.</span>new
person<span style="color: #990000">.</span>valid? <span style="font-style: italic"><span style="color: #9A1900"># =&gt; false</span></span>
person<span style="color: #990000">.</span>errors<span style="color: #990000">.</span>on<span style="color: #990000">(:</span>name<span style="color: #990000">)</span>
<span style="font-style: italic"><span style="color: #9A1900"># =&gt; ["can't be blank", "is too short (minimum is 3 characters)"]</span></span>
</tt></pre></div></div>
<div class="ilist"><ul>
<span style="font-style: italic"><span style="color: #9A1900"># =&gt; ["can't be blank", "is too short (minimum is 3 characters)"]</span></span></tt></pre></div></div>
<div class="ulist"><ul>
<li>
<p>
<tt>clear</tt> is used when you intentionally want to clear all the messages in the <tt>errors</tt> collection. However, calling <tt>errors.clear</tt> upon an invalid object won't make it valid: the <tt>errors</tt> collection will now be empty, but the next time you call <tt>valid?</tt> or any method that tries to save this object to the database, the validations will run. If any of them fails, the <tt>errors</tt> collection will get filled again.
<tt>clear</tt> is used when you intentionally want to clear all the messages in the <tt>errors</tt> collection. However, calling <tt>errors.clear</tt> upon an invalid object won&#8217;t make it valid: the <tt>errors</tt> collection will now be empty, but the next time you call <tt>valid?</tt> or any method that tries to save this object to the database, the validations will run. If any of them fails, the <tt>errors</tt> collection will get filled again.
</p>
</li>
</ul></div>
@@ -922,16 +893,15 @@ person<span style="color: #990000">.</span>errors<span style="color: #990000">.<
person<span style="color: #990000">.</span>errors<span style="color: #990000">.</span>empty? <span style="font-style: italic"><span style="color: #9A1900"># =&gt; true</span></span>
p<span style="color: #990000">.</span>save <span style="font-style: italic"><span style="color: #9A1900"># =&gt; false</span></span>
p<span style="color: #990000">.</span>errors<span style="color: #990000">.</span>on<span style="color: #990000">(:</span>name<span style="color: #990000">)</span>
<span style="font-style: italic"><span style="color: #9A1900"># =&gt; ["can't be blank", "is too short (minimum is 3 characters)"]</span></span>
</tt></pre></div></div>
<span style="font-style: italic"><span style="color: #9A1900"># =&gt; ["can't be blank", "is too short (minimum is 3 characters)"]</span></span></tt></pre></div></div>
</div>
<h2 id="_callbacks">8. Callbacks</h2>
<div class="sectionbody">
<div class="para"><p>Callbacks are methods that get called at certain moments of an object's lifecycle. With callbacks it's possible to write code that will run whenever an Active Record object is created, saved, updated, deleted or loaded from the database.</p></div>
<div class="paragraph"><p>Callbacks are methods that get called at certain moments of an object&#8217;s lifecycle. With callbacks it&#8217;s possible to write code that will run whenever an Active Record object is created, saved, updated, deleted or loaded from the database.</p></div>
<h3 id="_callbacks_registration">8.1. Callbacks registration</h3>
<div class="para"><p>In order to use the available callbacks, you need to registrate them. There are two ways of doing that.</p></div>
<div class="paragraph"><p>In order to use the available callbacks, you need to registrate them. There are two ways of doing that.</p></div>
<h3 id="_registering_callbacks_by_overriding_the_callback_methods">8.2. Registering callbacks by overriding the callback methods</h3>
<div class="para"><p>You can specify the callback method directly, by overriding it. Let's see how it works using the <tt>before_validation</tt> callback, which will surprisingly run right before any validation is done.</p></div>
<div class="paragraph"><p>You can specify the callback method directly, by overriding it. Let&#8217;s see how it works using the <tt>before_validation</tt> callback, which will surprisingly run right before any validation is done.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -946,10 +916,9 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>login <span style="color: #990000">=</span> email <span style="font-weight: bold"><span style="color: #0000FF">unless</span></span> email<span style="color: #990000">.</span>blank?
<span style="font-weight: bold"><span style="color: #0000FF">end</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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<h3 id="_registering_callbacks_by_using_macro_style_class_methods">8.3. Registering callbacks by using macro-style class methods</h3>
<div class="para"><p>The other way you can register a callback method is by implementing it as an ordinary method, and then using a macro-style class method to register it as a callback. The last example could be written like that:</p></div>
<div class="paragraph"><p>The other way you can register a callback method is by implementing it as an ordinary method, and then using a macro-style class method to register it as a callback. The last example could be written like that:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -966,9 +935,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>login <span style="color: #990000">=</span> email <span style="font-weight: bold"><span style="color: #0000FF">unless</span></span> email<span style="color: #990000">.</span>blank?
<span style="font-weight: bold"><span style="color: #0000FF">end</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>The macro-style class methods can also receive a block. Rails best practices say that you should only use this style of registration if the code inside your block is so short that it fits in just one line.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The macro-style class methods can also receive a block. Rails best practices say that you should only use this style of registration if the code inside your block is so short that it fits in just one line.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -978,10 +946,9 @@ http://www.gnu.org/software/src-highlite -->
validates_presence_of <span style="color: #990000">:</span>login<span style="color: #990000">,</span> <span style="color: #990000">:</span>email
before_create <span style="color: #FF0000">{</span><span style="color: #990000">|</span>user<span style="color: #990000">|</span> user<span style="color: #990000">.</span>name <span style="color: #990000">=</span> user<span style="color: #990000">.</span>login<span style="color: #990000">.</span>capitalize <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> user<span style="color: #990000">.</span>name<span style="color: #990000">.</span>blank?<span style="color: #FF0000">}</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>In Rails, the preferred way of registering callbacks is by using macro-style class methods. The main advantages of using macro-style class methods are:</p></div>
<div class="ilist"><ul>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>In Rails, the preferred way of registering callbacks is by using macro-style class methods. The main advantages of using macro-style class methods are:</p></div>
<div class="ulist"><ul>
<li>
<p>
You can add more than one method for each type of callback. Those methods will be queued for execution at the same order they were registered.
@@ -1004,9 +971,9 @@ Readability, since your callback declarations will live at the beggining of your
</div>
<h2 id="_available_callbacks">9. Available callbacks</h2>
<div class="sectionbody">
<div class="para"><p>Here is a list with all the available Active Record callbacks, listed in the same order in which they will get called during the respective operations.</p></div>
<div class="paragraph"><p>Here is a list with all the available Active Record callbacks, listed in the same order in which they will get called during the respective operations.</p></div>
<h3 id="_callbacks_called_both_when_creating_or_updating_a_record">9.1. Callbacks called both when creating or updating a record.</h3>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<tt>before_validation</tt>
@@ -1034,7 +1001,7 @@ Readability, since your callback declarations will live at the beggining of your
</li>
</ul></div>
<h3 id="_callbacks_called_only_when_creating_a_new_record">9.2. Callbacks called only when creating a new record.</h3>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<tt>before_validation_on_create</tt>
@@ -1062,7 +1029,7 @@ Readability, since your callback declarations will live at the beggining of your
</li>
</ul></div>
<h3 id="_callbacks_called_only_when_updating_an_existing_record">9.3. Callbacks called only when updating an existing record.</h3>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<tt>before_validation_on_update</tt>
@@ -1090,7 +1057,7 @@ Readability, since your callback declarations will live at the beggining of your
</li>
</ul></div>
<h3 id="_callbacks_called_when_removing_a_record_from_the_database">9.4. Callbacks called when removing a record from the database.</h3>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<tt>before_destroy</tt>
@@ -1107,20 +1074,20 @@ Readability, since your callback declarations will live at the beggining of your
</p>
</li>
</ul></div>
<div class="para"><p>The <tt>before_destroy</tt> and <tt>after_destroy</tt> callbacks will only be called if you delete the model using either the <tt>destroy</tt> instance method or one of the <tt>destroy</tt> or <tt>destroy_all</tt> class methods of your Active Record class. If you use <tt>delete</tt> or <tt>delete_all</tt> no callback operations will run, since Active Record will not instantiate any objects, accessing the records to be deleted directly in the database.</p></div>
<div class="paragraph"><p>The <tt>before_destroy</tt> and <tt>after_destroy</tt> callbacks will only be called if you delete the model using either the <tt>destroy</tt> instance method or one of the <tt>destroy</tt> or <tt>destroy_all</tt> class methods of your Active Record class. If you use <tt>delete</tt> or <tt>delete_all</tt> no callback operations will run, since Active Record will not instantiate any objects, accessing the records to be deleted directly in the database.</p></div>
<h3 id="_the_tt_after_initialize_tt_and_tt_after_find_tt_callbacks">9.5. The <tt>after_initialize</tt> and <tt>after_find</tt> callbacks</h3>
<div class="para"><p>The <tt>after_initialize</tt> callback will be called whenever an Active Record object is instantiated, either by direcly using <tt>new</tt> or when a record is loaded from the database. It can be useful to avoid the need to directly override your Active Record <tt>initialize</tt> method.</p></div>
<div class="para"><p>The <tt>after_find</tt> callback will be called whenever Active Record loads a record from the database. When used together with <tt>after_initialize</tt> it will run first, since Active Record will first read the record from the database and them create the model object that will hold it.</p></div>
<div class="para"><p>The <tt>after_initialize</tt> and <tt>after_find</tt> callbacks are a bit different from the others, since the only way to register those callbacks is by defining them as methods. If you try to register <tt>after_initialize</tt> or <tt>after_find</tt> using macro-style class methods, they will just be ignored. This behaviour is due to performance reasons, since <tt>after_initialize</tt> and <tt>after_find</tt> will both be called for each record found in the database, significantly slowing down the queries.</p></div>
<div class="paragraph"><p>The <tt>after_initialize</tt> callback will be called whenever an Active Record object is instantiated, either by direcly using <tt>new</tt> or when a record is loaded from the database. It can be useful to avoid the need to directly override your Active Record <tt>initialize</tt> method.</p></div>
<div class="paragraph"><p>The <tt>after_find</tt> callback will be called whenever Active Record loads a record from the database. When used together with <tt>after_initialize</tt> it will run first, since Active Record will first read the record from the database and them create the model object that will hold it.</p></div>
<div class="paragraph"><p>The <tt>after_initialize</tt> and <tt>after_find</tt> callbacks are a bit different from the others, since the only way to register those callbacks is by defining them as methods. If you try to register <tt>after_initialize</tt> or <tt>after_find</tt> using macro-style class methods, they will just be ignored. This behaviour is due to performance reasons, since <tt>after_initialize</tt> and <tt>after_find</tt> will both be called for each record found in the database, significantly slowing down the queries.</p></div>
</div>
<h2 id="_halting_execution">10. Halting Execution</h2>
<div class="sectionbody">
<div class="para"><p>As you start registering new callbacks for your models, they will be queued for execution. This queue will include all your model's validations, the registered callbacks and the database operation to be executed. However, if at any moment one of the <tt>before_create</tt>, <tt>before_save</tt>, <tt>before_update</tt> or <tt>before_destroy</tt> callback methods returns a boolean <tt>false</tt> (not <tt>nil</tt>) value, this execution chain will be halted and the desired operation will not complete: your model will not get persisted in the database, or your records will not get deleted and so on.</p></div>
<div class="paragraph"><p>As you start registering new callbacks for your models, they will be queued for execution. This queue will include all your model&#8217;s validations, the registered callbacks and the database operation to be executed. However, if at any moment one of the <tt>before_create</tt>, <tt>before_save</tt>, <tt>before_update</tt> or <tt>before_destroy</tt> callback methods returns a boolean <tt>false</tt> (not <tt>nil</tt>) value, this execution chain will be halted and the desired operation will not complete: your model will not get persisted in the database, or your records will not get deleted and so on.</p></div>
</div>
<h2 id="_callback_classes">11. Callback classes</h2>
<div class="sectionbody">
<div class="para"><p>Sometimes the callback methods that you'll write will be useful enough to be reused at other models. Active Record makes it possible to create classes that encapsulate the callback methods, so it becomes very easy to reuse them.</p></div>
<div class="para"><p>Here's an example where we create a class with a after_destroy callback for a PictureFile model.</p></div>
<div class="paragraph"><p>Sometimes the callback methods that you&#8217;ll write will be useful enough to be reused at other models. Active Record makes it possible to create classes that encapsulate the callback methods, so it becomes very easy to reuse them.</p></div>
<div class="paragraph"><p>Here&#8217;s an example where we create a class with a after_destroy callback for a PictureFile model.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1130,9 +1097,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> after_destroy<span style="color: #990000">(</span>picture_file<span style="color: #990000">)</span>
File<span style="color: #990000">.</span>delete<span style="color: #990000">(</span>picture_file<span style="color: #990000">.</span>filepath<span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> File<span style="color: #990000">.</span>exists?<span style="color: #990000">(</span>picture_file<span style="color: #990000">.</span>filepath<span style="color: #990000">)</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>When declared inside a class the callback method will receive the model object as a parameter. We can now use it this way:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>When declared inside a class the callback method will receive the model object as a parameter. We can now use it this way:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1140,9 +1106,8 @@ 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> PictureFile <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
after_destroy PictureFileCallbacks<span style="color: #990000">.</span>new
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>Note that we needed to instantiate a new PictureFileCallbacks object, since we declared our callback as an instance method. Sometimes it will make more sense to have it as a class method.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Note that we needed to instantiate a new PictureFileCallbacks object, since we declared our callback as an instance method. Sometimes it will make more sense to have it as a class method.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1152,9 +1117,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>after_destroy<span style="color: #990000">(</span>picture_file<span style="color: #990000">)</span>
File<span style="color: #990000">.</span>delete<span style="color: #990000">(</span>picture_file<span style="color: #990000">.</span>filepath<span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> File<span style="color: #990000">.</span>exists?<span style="color: #990000">(</span>picture_file<span style="color: #990000">.</span>filepath<span style="color: #990000">)</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>If the callback method is declared this way, it won't be necessary to instantiate a PictureFileCallbacks object.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>If the callback method is declared this way, it won&#8217;t be necessary to instantiate a PictureFileCallbacks object.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1162,16 +1126,15 @@ 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> PictureFile <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
after_destroy PictureFileCallbacks
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>You can declare as many callbacks as you want inside your callback classes.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>You can declare as many callbacks as you want inside your callback classes.</p></div>
</div>
<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="paragraph"><p>Active Record callbacks are a powerful feature, but they can pollute your model implementation with code that&#8217;s not directly related to the model&#8217;s purpose. In object-oriented software, it&#8217;s always a good idea to design your classes with a single responsability in the whole system. For example, it wouldn&#8217;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&#8217;re using callbacks to write code that&#8217;s not directly related to your model class purposes, it may be a good moment to create an Observer.</p></div>
<div class="paragraph"><p>An Active Record Observer is an object that links itself to a model and register it&#8217;s methods for callbacks. Your model&#8217;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&#8217;s implementation.</p></div>
<div class="paragraph"><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="paragraph"><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&#8217;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
@@ -1181,10 +1144,9 @@ http://www.gnu.org/software/src-highlite -->
<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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Like in callback classes, the observer&#8217;s methods receive the observed model as a parameter.</p></div>
<div class="paragraph"><p>Sometimes using the ModelName + Observer naming convention won&#8217;t be the best choice, mainly when you want to use the same observer for more than one model class. It&#8217;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
@@ -1192,26 +1154,24 @@ 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>
<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 them somewhere. The usual place to do that is 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="paragraph"><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 them somewhere. The usual place to do that is in our application&#8217;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>
<div class="para"><p>You can uncomment the line with <tt>config.active_record.observers</tt> and change the symbols for the name of the observers that should be registered.</p></div>
<div class="para"><p>It's also possible to register callbacks in any of the files living at <strong>config/environments/</strong>, if you want an observer to work only in a specific environment. There is not a <tt>config.active_record.observers</tt> line at any of those files, but you can simply add it.</p></div>
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>
<div class="paragraph"><p>You can uncomment the line with <tt>config.active_record.observers</tt> and change the symbols for the name of the observers that should be registered.</p></div>
<div class="paragraph"><p>It&#8217;s also possible to register callbacks in any of the files living at <strong>config/environments/</strong>, if you want an observer to work only in a specific environment. There is not a <tt>config.active_record.observers</tt> line at any of those files, but you can simply add it.</p></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 class="paragraph"><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 class="paragraph"><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>
</div>

File diff suppressed because it is too large Load Diff

View File

@@ -202,39 +202,39 @@ ul#navMain {
<div class="sidebarblock" id="fcheung">
<div class="sidebar-content">
<div class="sidebar-title">Frederick Cheung</div>
<div class="para"><p>Frederick Cheung is Chief Wizard at Texperts where he has been using Rails since 2006.
<div class="paragraph"><p>Frederick Cheung is Chief Wizard at Texperts where he has been using Rails since 2006.
He is based in Cambridge (UK) and when not consuming fine ales he blogs at <a href="http://www.spacevatican.org">spacevatican.org</a>.</p></div>
</div></div>
<div class="sidebarblock" id="mgunderloy">
<div class="sidebar-content">
<div class="sidebar-title">Mike Gunderloy</div>
<div class="para"><p>Mike Gunderloy is an independent consultant who brings 25 years of experience in a variety of languages to bear on his current
<div class="paragraph"><p>Mike Gunderloy is an independent consultant who brings 25 years of experience in a variety of languages to bear on his current
work with Rails. His near-daily links and other blogging can be found at <a href="http://afreshcup.com">A Fresh Cup</a>.</p></div>
</div></div>
<div class="sidebarblock" id="miloops">
<div class="sidebar-content">
<div class="sidebar-title">Emilio Tagua</div>
<div class="para"><p>Emilio Tagua &#8212; a.k.a. miloops &#8212; is an Argentinian entrepreneur, developer, open source contributor and Rails evangelist.
<div class="paragraph"><p>Emilio Tagua&#8201;&#8212;&#8201;a.k.a. miloops&#8201;&#8212;&#8201;is an Argentinian entrepreneur, developer, open source contributor and Rails evangelist.
Cofounder of <a href="http://www.eventioz.com">Eventioz</a>. He has been using Rails since 2006 and contributing since early 2008.
Can be found at gmail, twitter, freenode, everywhere as miloops.</p></div>
</div></div>
<div class="sidebarblock" id="hawe">
<div class="sidebar-content">
<div class="sidebar-title">Heiko Webers</div>
<div class="para"><p>Heiko Webers is the founder of <a href="http://www.bauland42.de">bauland42</a>, a German web application security consulting and development
<div class="paragraph"><p>Heiko Webers is the founder of <a href="http://www.bauland42.de">bauland42</a>, a German web application security consulting and development
company focused on Ruby on Rails. He blogs at <a href="http://www.rorsecurity.info">http://www.rorsecurity.info</a>. After 10 years of desktop application development,
Heiko has rarely looked back.</p></div>
</div></div>
<div class="sidebarblock" id="toretore">
<div class="sidebar-content">
<div class="sidebar-title">Tore Darell</div>
<div class="para"><p>Tore Darell is an independent developer based in Menton, France who specialises in cruft-free web applications using Ruby, Rails
<div class="paragraph"><p>Tore Darell is an independent developer based in Menton, France who specialises in cruft-free web applications using Ruby, Rails
and unobtrusive JavaScript. His home on the internet is his blog <a href="http://tore.darell.no/">Sneaky Abstractions</a>.</p></div>
</div></div>
<div class="sidebarblock" id="zilkey">
<div class="sidebar-content">
<div class="sidebar-title">Jeff Dean</div>
<div class="para"><p>Jeff Dean is a software engineer with <a href="http://pivotallabs.com/">Pivotal Labs</a>.</p></div>
<div class="paragraph"><p>Jeff Dean is a software engineer with <a href="http://pivotallabs.com/">Pivotal Labs</a>.</p></div>
</div></div>
</div>
</div>

View File

@@ -222,7 +222,7 @@ ul#navMain {
<li><a href="#_preparing_ruby_and_ruby_prof">Preparing Ruby and Ruby-prof</a></li>
<li><a href="#_installing_jeremy_kemper_s_ruby_prof">Installing Jeremy Kemper's ruby-prof</a></li>
<li><a href="#_installing_jeremy_kemper_8217_s_ruby_prof">Installing Jeremy Kemper&#8217;s ruby-prof</a></li>
<li><a href="#_generating_performance_test">Generating performance test</a></li>
@@ -287,8 +287,8 @@ ul#navMain {
<h1>Benchmarking and Profiling Rails</h1>
<div id="preamble">
<div class="sectionbody">
<div class="para"><p>This guide covers the benchmarking and profiling tactics/tools of Rails and Ruby in general. By referring to this guide, you will be able to:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>This guide covers the benchmarking and profiling tactics/tools of Rails and Ruby in general. By referring to this guide, you will be able to:</p></div>
<div class="ulist"><ul>
<li>
<p>
Understand the various types of benchmarking and profiling metrics
@@ -319,13 +319,13 @@ Learn about various tools facilitating benchmarking and profiling
</div>
<h2 id="_why_benchmark_and_profile">1. Why Benchmark and Profile ?</h2>
<div class="sectionbody">
<div class="para"><p>Benchmarking and Profiling is an integral part of the development cycle. It is very important that you don't make your end users wait for too long before the page is completely loaded. Ensuring a plesant browsing experience to the end users and cutting cost of unnecessary hardwares is important for any web application.</p></div>
<div class="paragraph"><p>Benchmarking and Profiling is an integral part of the development cycle. It is very important that you don&#8217;t make your end users wait for too long before the page is completely loaded. Ensuring a plesant browsing experience to the end users and cutting cost of unnecessary hardwares is important for any web application.</p></div>
<h3 id="_what_is_the_difference_between_benchmarking_and_profiling">1.1. What is the difference between benchmarking and profiling ?</h3>
<div class="para"><p>Benchmarking is the process of finding out if a piece of code is slow or not. Whereas profiling is the process of finding out what exactly is slowing down that piece of code.</p></div>
<div class="paragraph"><p>Benchmarking is the process of finding out if a piece of code is slow or not. Whereas profiling is the process of finding out what exactly is slowing down that piece of code.</p></div>
</div>
<h2 id="_using_and_understanding_the_log_files">2. Using and understanding the log files</h2>
<div class="sectionbody">
<div class="para"><p>Rails logs files containt basic but very useful information about the time taken to serve every request. A typical log entry looks something like :</p></div>
<div class="paragraph"><p>Rails logs files containt basic but very useful information about the time taken to serve every request. A typical log entry looks something like :</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -336,21 +336,19 @@ http://www.gnu.org/software/src-highlite -->
Parameters<span style="color: #990000">:</span> <span style="color: #FF0000">{</span><span style="color: #FF0000">"action"</span><span style="color: #990000">=&gt;</span><span style="color: #FF0000">"index"</span><span style="color: #990000">,</span> <span style="color: #FF0000">"controller"</span><span style="color: #990000">=&gt;</span><span style="color: #FF0000">"items"</span><span style="color: #FF0000">}</span>
Rendering template within layouts<span style="color: #990000">/</span>items
Rendering items<span style="color: #990000">/</span>index
Completed <span style="font-weight: bold"><span style="color: #0000FF">in</span></span> 5ms <span style="color: #990000">(</span>View<span style="color: #990000">:</span> <span style="color: #993399">2</span><span style="color: #990000">,</span> DB<span style="color: #990000">:</span> <span style="color: #993399">0</span><span style="color: #990000">)</span> <span style="color: #990000">|</span> <span style="color: #993399">200</span> OK <span style="color: #990000">[</span>http<span style="color: #990000">:</span><span style="color: #FF6600">//localhost/</span>items<span style="color: #990000">]</span>
</tt></pre></div></div>
<div class="para"><p>For this section, we're only interested in the last line from that log entry:</p></div>
Completed <span style="font-weight: bold"><span style="color: #0000FF">in</span></span> 5ms <span style="color: #990000">(</span>View<span style="color: #990000">:</span> <span style="color: #993399">2</span><span style="color: #990000">,</span> DB<span style="color: #990000">:</span> <span style="color: #993399">0</span><span style="color: #990000">)</span> <span style="color: #990000">|</span> <span style="color: #993399">200</span> OK <span style="color: #990000">[</span>http<span style="color: #990000">:</span><span style="color: #FF6600">//localhost/</span>items<span style="color: #990000">]</span></tt></pre></div></div>
<div class="paragraph"><p>For this section, we&#8217;re only interested in the last line from that log entry:</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>Completed <span style="font-weight: bold"><span style="color: #0000FF">in</span></span> 5ms <span style="color: #990000">(</span>View<span style="color: #990000">:</span> <span style="color: #993399">2</span><span style="color: #990000">,</span> DB<span style="color: #990000">:</span> <span style="color: #993399">0</span><span style="color: #990000">)</span> <span style="color: #990000">|</span> <span style="color: #993399">200</span> OK <span style="color: #990000">[</span>http<span style="color: #990000">:</span><span style="color: #FF6600">//localhost/</span>items<span style="color: #990000">]</span>
</tt></pre></div></div>
<div class="para"><p>This data is fairly straight forward to understand. Rails uses millisecond(ms) as the metric to measures the time taken. The complete request spent 5 ms inside Rails, out of which 2 ms were spent rendering views and none was spent communication with the database. It's safe to assume that the remaining 3 ms were spent inside the controller.</p></div>
<pre><tt>Completed <span style="font-weight: bold"><span style="color: #0000FF">in</span></span> 5ms <span style="color: #990000">(</span>View<span style="color: #990000">:</span> <span style="color: #993399">2</span><span style="color: #990000">,</span> DB<span style="color: #990000">:</span> <span style="color: #993399">0</span><span style="color: #990000">)</span> <span style="color: #990000">|</span> <span style="color: #993399">200</span> OK <span style="color: #990000">[</span>http<span style="color: #990000">:</span><span style="color: #FF6600">//localhost/</span>items<span style="color: #990000">]</span></tt></pre></div></div>
<div class="paragraph"><p>This data is fairly straight forward to understand. Rails uses millisecond(ms) as the metric to measures the time taken. The complete request spent 5 ms inside Rails, out of which 2 ms were spent rendering views and none was spent communication with the database. It&#8217;s safe to assume that the remaining 3 ms were spent inside the controller.</p></div>
</div>
<h2 id="_helper_methods">3. Helper methods</h2>
<div class="sectionbody">
<div class="para"><p>Rails provides various helper methods inside Active Record, Action Controller and Action View to measure the time taken by a specific code. The method is called <tt>benchmark()</tt> in all three components.</p></div>
<div class="paragraph"><p>Rails provides various helper methods inside Active Record, Action Controller and Action View to measure the time taken by a specific code. The method is called <tt>benchmark()</tt> in all three components.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -360,18 +358,16 @@ http://www.gnu.org/software/src-highlite -->
project <span style="color: #990000">=</span> Project<span style="color: #990000">.</span>create<span style="color: #990000">(</span><span style="color: #FF0000">"name"</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"stuff"</span><span style="color: #990000">)</span>
project<span style="color: #990000">.</span>create_manager<span style="color: #990000">(</span><span style="color: #FF0000">"name"</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"David"</span><span style="color: #990000">)</span>
project<span style="color: #990000">.</span>milestones <span style="color: #990000">&lt;&lt;</span> Milestone<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">)</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The above code benchmarks the multiple statments enclosed inside <tt>Project.benchmark("Creating project") do..end</tt> block and prints the results inside log files. The statement inside log files will look like:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The above code benchmarks the multiple statments enclosed inside <tt>Project.benchmark("Creating project") do..end</tt> block and prints the results inside log files. The statement inside log files will look like:</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>Creating projectem <span style="color: #990000">(</span><span style="color: #993399">185</span><span style="color: #990000">.</span>3ms<span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>Please refer to <a href="http://api.rubyonrails.com/classes/ActiveRecord/Base.html#M001336">API docs</a> for optional options to <tt>benchmark()</tt></p></div>
<div class="para"><p>Similarly, you could use this helper method inside <a href="http://api.rubyonrails.com/classes/ActionController/Benchmarking/ClassMethods.html#M000715">controllers</a> ( Note that it's a class method here ):</p></div>
<pre><tt>Creating projectem <span style="color: #990000">(</span><span style="color: #993399">185</span><span style="color: #990000">.</span>3ms<span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>Please refer to <a href="http://api.rubyonrails.com/classes/ActiveRecord/Base.html#M001336">API docs</a> for optional options to <tt>benchmark()</tt></p></div>
<div class="paragraph"><p>Similarly, you could use this helper method inside <a href="http://api.rubyonrails.com/classes/ActionController/Benchmarking/ClassMethods.html#M000715">controllers</a> ( Note that it&#8217;s a class method here ):</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -382,9 +378,8 @@ http://www.gnu.org/software/src-highlite -->
Project<span style="color: #990000">.</span>process<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>project_ids<span style="color: #990000">])</span>
Project<span style="color: #990000">.</span>update_cached_projects
<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>and <a href="http://api.rubyonrails.com/classes/ActionController/Benchmarking/ClassMethods.html#M000715">views</a>:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>and <a href="http://api.rubyonrails.com/classes/ActionController/Benchmarking/ClassMethods.html#M000715">views</a>:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -392,13 +387,12 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #FF0000">&lt;% benchmark("Showing projects partial") do %&gt;</span>
<span style="color: #FF0000">&lt;%= render :partial =&gt;</span> <span style="color: #009900">@projects</span> <span style="color: #990000">%&gt;</span>
<span style="color: #FF0000">&lt;% end %&gt;</span>
</tt></pre></div></div>
<span style="color: #FF0000">&lt;% end %&gt;</span></tt></pre></div></div>
</div>
<h2 id="_performance_test_cases">4. Performance Test Cases</h2>
<div class="sectionbody">
<div class="para"><p>Rails provides a very easy to write performance test cases, which look just like the regular integration tests.</p></div>
<div class="para"><p>If you have a look at <tt>test/performance/browsing_test.rb</tt> in a newly created Rails application:</p></div>
<div class="paragraph"><p>Rails provides a very easy to write performance test cases, which look just like the regular integration tests.</p></div>
<div class="paragraph"><p>If you have a look at <tt>test/performance/browsing_test.rb</tt> in a newly created Rails application:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -412,25 +406,24 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_homepage
get <span style="color: #FF0000">'/'</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>This is an automatically generated example performance test file, for testing performance of homepage(<em>/</em>) of the application.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This is an automatically generated example performance test file, for testing performance of homepage(<em>/</em>) of the application.</p></div>
<h3 id="_modes">4.1. Modes</h3>
<h4 id="_benchmarking">4.1.1. Benchmarking</h4>
<h4 id="_profiling">4.1.2. Profiling</h4>
<h3 id="_metrics">4.2. Metrics</h3>
<h4 id="_process_time">4.2.1. Process Time</h4>
<div class="para"><p>CPU Cycles.</p></div>
<div class="paragraph"><p>CPU Cycles.</p></div>
<h4 id="_memory">4.2.2. Memory</h4>
<div class="para"><p>Memory taken.</p></div>
<div class="paragraph"><p>Memory taken.</p></div>
<h4 id="_objects">4.2.3. Objects</h4>
<div class="para"><p>Objects allocated.</p></div>
<div class="paragraph"><p>Objects allocated.</p></div>
<h4 id="_gc_runs">4.2.4. GC Runs</h4>
<div class="para"><p>Number of times the Ruby GC was run.</p></div>
<div class="paragraph"><p>Number of times the Ruby GC was run.</p></div>
<h4 id="_gc_time">4.2.5. GC Time</h4>
<div class="para"><p>Time spent running the Ruby GC.</p></div>
<div class="paragraph"><p>Time spent running the Ruby GC.</p></div>
<h3 id="_preparing_ruby_and_ruby_prof">4.3. Preparing Ruby and Ruby-prof</h3>
<div class="para"><p>Before we go ahead, Rails performance testing requires you to build a special Ruby binary with some super powers - GC patch for measuring GC Runs/Time. This process is very straight forward. If you've never compiled a Ruby binary before, you can follow the following steps to build a ruby binary inside your home directory:</p></div>
<div class="paragraph"><p>Before we go ahead, Rails performance testing requires you to build a special Ruby binary with some super powers - GC patch for measuring GC Runs/Time. This process is very straight forward. If you&#8217;ve never compiled a Ruby binary before, you can follow the following steps to build a ruby binary inside your home directory:</p></div>
<h4 id="_compile">4.3.1. Compile</h4>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
@@ -443,10 +436,9 @@ http://www.gnu.org/software/src-highlite -->
<span style="color: #990000">[</span>lifo@null <span style="color: #990000">~]</span>$ cd ruby-<span style="color: #993399">1.8</span><span style="color: #990000">.</span><span style="color: #993399">6</span>-p<span style="color: #993399">111</span>
<span style="color: #990000">[</span>lifo@null ruby-<span style="color: #993399">1.8</span><span style="color: #990000">.</span><span style="color: #993399">6</span>-p<span style="color: #993399">111</span><span style="color: #990000">]</span>$ curl http<span style="color: #990000">:</span>//rubyforge<span style="color: #990000">.</span>org/tracker/download<span style="color: #990000">.</span>php<span style="color: #990000">/</span><span style="color: #993399">1814</span><span style="color: #990000">/</span><span style="color: #993399">7062</span><span style="color: #990000">/</span><span style="color: #993399">17676</span><span style="color: #990000">/</span><span style="color: #993399">3291</span>/ruby186gc<span style="color: #990000">.</span>patch <span style="color: #990000">|</span> patch -p<span style="color: #993399">0</span>
<span style="color: #990000">[</span>lifo@null ruby-<span style="color: #993399">1.8</span><span style="color: #990000">.</span><span style="color: #993399">6</span>-p<span style="color: #993399">111</span><span style="color: #990000">]</span>$ <span style="color: #990000">.</span>/configure --prefix<span style="color: #990000">=</span>/Users/lifo/rubygc
<span style="color: #990000">[</span>lifo@null ruby-<span style="color: #993399">1.8</span><span style="color: #990000">.</span><span style="color: #993399">6</span>-p<span style="color: #993399">111</span><span style="color: #990000">]</span>$ make <span style="color: #990000">&amp;&amp;</span> make install
</tt></pre></div></div>
<span style="color: #990000">[</span>lifo@null ruby-<span style="color: #993399">1.8</span><span style="color: #990000">.</span><span style="color: #993399">6</span>-p<span style="color: #993399">111</span><span style="color: #990000">]</span>$ make <span style="color: #990000">&amp;&amp;</span> make install</tt></pre></div></div>
<h4 id="_prepare_aliases">4.3.2. Prepare aliases</h4>
<div class="para"><p>Add the following lines in your ~/.profile for convenience:</p></div>
<div class="paragraph"><p>Add the following lines in your ~/.profile for convenience:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>alias gcruby='/Users/lifo/rubygc/bin/ruby'
@@ -471,15 +463,15 @@ alias gcrails='/Users/lifo/rubygc/bin/rails'</tt></pre>
<div class="content">
<pre><tt>[lifo@null ~]$ gcgem install mysql</tt></pre>
</div></div>
<div class="para"><p>If this fails, you can try to install it manually:</p></div>
<div class="paragraph"><p>If this fails, you can try to install it manually:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>[lifo@null ~]$ cd /Users/lifo/rubygc/lib/ruby/gems/1.8/gems/mysql-2.7/
[lifo@null mysql-2.7]$ gcruby extconf.rb --with-mysql-config
[lifo@null mysql-2.7]$ make &amp;&amp; make install</tt></pre>
</div></div>
<h3 id="_installing_jeremy_kemper_s_ruby_prof">4.4. Installing Jeremy Kemper's ruby-prof</h3>
<div class="para"><p>We also need to install Jeremy's ruby-prof gem using our newly built ruby:</p></div>
<h3 id="_installing_jeremy_kemper_8217_s_ruby_prof">4.4. Installing Jeremy Kemper&#8217;s ruby-prof</h3>
<div class="paragraph"><p>We also need to install Jeremy&#8217;s ruby-prof gem using our newly built ruby:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -488,18 +480,16 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #990000">[</span>lifo@null <span style="color: #990000">~]</span>$ git clone git<span style="color: #990000">:</span>//github<span style="color: #990000">.</span>com/jeremy/ruby-prof<span style="color: #990000">.</span>git
<span style="color: #990000">[</span>lifo@null <span style="color: #990000">~]</span>$ cd ruby-prof<span style="color: #990000">/</span>
<span style="color: #990000">[</span>lifo@null ruby-prof <span style="color: #990000">(</span>master<span style="color: #990000">)]</span>$ gcrake gem
<span style="color: #990000">[</span>lifo@null ruby-prof <span style="color: #990000">(</span>master<span style="color: #990000">)]</span>$ gcgem install pkg/ruby-prof-<span style="color: #993399">0.6</span><span style="color: #990000">.</span><span style="color: #993399">1</span><span style="color: #990000">.</span>gem
</tt></pre></div></div>
<span style="color: #990000">[</span>lifo@null ruby-prof <span style="color: #990000">(</span>master<span style="color: #990000">)]</span>$ gcgem install pkg/ruby-prof-<span style="color: #993399">0.6</span><span style="color: #990000">.</span><span style="color: #993399">1</span><span style="color: #990000">.</span>gem</tt></pre></div></div>
<h3 id="_generating_performance_test">4.5. Generating performance test</h3>
<div class="para"><p>Rails provides a simple generator for creating new performance tests:</p></div>
<div class="paragraph"><p>Rails provides a simple generator for creating new performance tests:</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="color: #990000">[</span>lifo@null application <span style="color: #990000">(</span>master<span style="color: #990000">)]</span>$ script/generate performance_test homepage
</tt></pre></div></div>
<div class="para"><p>This will generate <tt>test/performance/homepage_test.rb</tt>:</p></div>
<pre><tt><span style="color: #990000">[</span>lifo@null application <span style="color: #990000">(</span>master<span style="color: #990000">)]</span>$ script/generate performance_test homepage</tt></pre></div></div>
<div class="paragraph"><p>This will generate <tt>test/performance/homepage_test.rb</tt>:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -513,25 +503,23 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_homepage
get <span style="color: #FF0000">'/'</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>Which you can modify to suit your needs.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Which you can modify to suit your needs.</p></div>
<h3 id="_running_tests">4.6. Running tests</h3>
</div>
<h2 id="_understanding_performance_tests_outputs">5. Understanding Performance Tests Outputs</h2>
<div class="sectionbody">
<h3 id="_our_first_performance_test">5.1. Our First Performance Test</h3>
<div class="para"><p>So how do we profile a request.</p></div>
<div class="para"><p>One of the things that is important to us is how long it takes to render the home page - so let's make a request to the home page. Once the request is complete, the results will be outputted in the terminal.</p></div>
<div class="para"><p>In the terminal run</p></div>
<div class="paragraph"><p>So how do we profile a request.</p></div>
<div class="paragraph"><p>One of the things that is important to us is how long it takes to render the home page - so let&#8217;s make a request to the home page. Once the request is complete, the results will be outputted in the terminal.</p></div>
<div class="paragraph"><p>In the terminal run</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="color: #990000">[</span>User profiling_tester<span style="color: #990000">]</span>$ gcruby tests<span style="color: #FF6600">/performance/</span>homepage<span style="color: #990000">.</span>rb
</tt></pre></div></div>
<div class="para"><p>After the tests runs for a few seconds you should see something like this.</p></div>
<pre><tt><span style="color: #990000">[</span>User profiling_tester<span style="color: #990000">]</span>$ gcruby tests<span style="color: #FF6600">/performance/</span>homepage<span style="color: #990000">.</span>rb</tt></pre></div></div>
<div class="paragraph"><p>After the tests runs for a few seconds you should see something like this.</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>HomepageTest#test_homepage (19 ms warmup)
@@ -541,8 +529,8 @@ http://www.gnu.org/software/src-highlite -->
Finished in 2.207428 seconds.</tt></pre>
</div></div>
<div class="para"><p>Simple but efficient.</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>Simple but efficient.</p></div>
<div class="ulist"><ul>
<li>
<p>
Process Time refers to amount of time necessary to complete the action.
@@ -559,9 +547,9 @@ object ??? #TODO find a good definition. Is it the amount of objects put into a
</p>
</li>
</ul></div>
<div class="para"><p>In addition we also gain three types of itemized log files for each of these outputs. They can be found in your tmp directory of your application.</p></div>
<div class="para"><p><strong>The Three types are</strong></p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>In addition we also gain three types of itemized log files for each of these outputs. They can be found in your tmp directory of your application.</p></div>
<div class="paragraph"><p><strong>The Three types are</strong></p></div>
<div class="ulist"><ul>
<li>
<p>
Flat File - A simple text file with the data laid out in a grid
@@ -586,12 +574,12 @@ Tree File - A file output that can be use in conjunction with KCachegrind to vis
<td class="content">KCachegrind is Linux only. For Mac this means you have to do a full KDE install to have it working in your OS. Which is over 3 gigs in size. For windows there is clone called wincachegrind but it is no longer actively being developed.</td>
</tr></table>
</div>
<div class="para"><p>Below are examples for Flat Files and Graphical Files</p></div>
<div class="paragraph"><p>Below are examples for Flat Files and Graphical Files</p></div>
<h3 id="_flat_files">5.2. Flat Files</h3>
<div class="exampleblock">
<div class="title">Example: Flat File Output Processing Time</div>
<div class="title">Flat File Output Processing Time</div>
<div class="exampleblock-content">
<div class="para"><p>Thread ID: 2279160
<div class="paragraph"><p>Thread ID: 2279160
Total: 0.026097</p></div>
<div class="literalblock">
<div class="content">
@@ -615,8 +603,8 @@ Total: 0.026097</p></div>
0.18 0.00 0.00 0.00 0.00 17 &lt;Class::Object&gt;#allocate</tt></pre>
</div></div>
</div></div>
<div class="para"><p>So what do these columns tell us:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>So what do these columns tell us:</p></div>
<div class="ulist"><ul>
<li>
<p>
%self - The percentage of time spent processing the method. This is derived from self_time/total_time
@@ -639,7 +627,7 @@ wait - Time processed was queued
</li>
<li>
<p>
child - The time spent in this method's children.
child - The time spent in this method&#8217;s children.
</p>
</li>
<li>
@@ -653,16 +641,16 @@ name - The name of the method.
</p>
</li>
</ul></div>
<div class="para"><p>Name can be displayed three seperate ways:
<strong> #toplevel - The root method that calls all other methods
</strong> MyObject#method - Example Hash#each, The class Hash is calling the method each
<div class="paragraph"><p>Name can be displayed three seperate ways:
* #toplevel - The root method that calls all other methods
* MyObject#method - Example Hash#each, The class Hash is calling the method each
* &lt;Object:MyObject&gt;#test - The &lt;&gt; characters indicate a singleton method on a singleton class. Example &lt;Class::Object&gt;#allocate</p></div>
<div class="para"><p>Methods are sorted based on %self. Hence the ones taking the most time and resources will be at the top.</p></div>
<div class="para"><p>So for Array#each which is calling each on the class array. We find that it processing time is 2% of the total and was called 15 times. The rest of the information is 0.00 because the process is so fast it isn't recording times less then 100 ms.</p></div>
<div class="paragraph"><p>Methods are sorted based on %self. Hence the ones taking the most time and resources will be at the top.</p></div>
<div class="paragraph"><p>So for Array#each which is calling each on the class array. We find that it processing time is 2% of the total and was called 15 times. The rest of the information is 0.00 because the process is so fast it isn&#8217;t recording times less then 100 ms.</p></div>
<div class="exampleblock">
<div class="title">Example: Flat File Memory Output</div>
<div class="title">Flat File Memory Output</div>
<div class="exampleblock-content">
<div class="para"><p>Thread ID: 2279160
<div class="paragraph"><p>Thread ID: 2279160
Total: 509.724609</p></div>
<div class="literalblock">
<div class="content">
@@ -676,12 +664,12 @@ Total: 509.724609</p></div>
1.01 5.13 5.13 0.00 0.00 27 Array#-</tt></pre>
</div></div>
</div></div>
<div class="para"><p>Very similar to the processing time format. The main difference here is that instead of calculating time we are now concerned with the amount of KB put into memory <strong>(or is it strictly into the heap) can I get clarification on this minor point?</strong></p></div>
<div class="para"><p>So for &lt;Module::YAML&gt;#quick_emit which is singleton method on the class YAML it uses 57.66 KB in total, 23.57 through its own actions, 6.69 from actions it calls itself and that it was called twice.</p></div>
<div class="paragraph"><p>Very similar to the processing time format. The main difference here is that instead of calculating time we are now concerned with the amount of KB put into memory <strong>(or is it strictly into the heap) can I get clarification on this minor point?</strong></p></div>
<div class="paragraph"><p>So for &lt;Module::YAML&gt;#quick_emit which is singleton method on the class YAML it uses 57.66 KB in total, 23.57 through its own actions, 6.69 from actions it calls itself and that it was called twice.</p></div>
<div class="exampleblock">
<div class="title">Example: Flat File Objects</div>
<div class="title">Flat File Objects</div>
<div class="exampleblock-content">
<div class="para"><p>Thread ID: 2279160
<div class="paragraph"><p>Thread ID: 2279160
Total: 6537.000000</p></div>
<div class="literalblock">
<div class="content">
@@ -700,13 +688,13 @@ Total: 6537.000000</p></div>
<pre><tt>#TODO Find correct terminology for how to describe what this is exactly profiling as in are there really 2203 array objects or 2203 pointers to array objects?.</tt></pre>
</div></div>
<h3 id="_graph_files">5.3. Graph Files</h3>
<div class="para"><p>While the information gleamed from flat files is very useful we still don't know which processes each method is calling. We only know how many. This is not true for a graph file. Below is a text representation of a graph file. The actual graph file is an html entity and an example of which can be found <a href="examples/graph.html">Here</a></p></div>
<div class="para"><p>#TODO (Handily the graph file has links both between it many processes and to the files that actually contain them for debugging.
<div class="paragraph"><p>While the information gleamed from flat files is very useful we still don&#8217;t know which processes each method is calling. We only know how many. This is not true for a graph file. Below is a text representation of a graph file. The actual graph file is an html entity and an example of which can be found <a href="examples/graph.html">Here</a></p></div>
<div class="paragraph"><p>#TODO (Handily the graph file has links both between it many processes and to the files that actually contain them for debugging.
)</p></div>
<div class="exampleblock">
<div class="title">Example: Graph File</div>
<div class="title">Graph File</div>
<div class="exampleblock-content">
<div class="para"><p>Thread ID: 21277412</p></div>
<div class="paragraph"><p>Thread ID: 21277412</p></div>
<div class="literalblock">
<div class="content">
<pre><tt> %total %self total self children calls Name
@@ -727,26 +715,26 @@ Total: 6537.000000</p></div>
/____________________________________________________________________________/</tt></pre>
</div></div>
</div></div>
<div class="para"><p>As you can see the calls have been separated into slices, no longer is the order determined by process time but instead from hierarchy. Each slice profiles a primary entry, with the primary entry's parents being shown above itself and it's children found below. A primary entry can be ascertained by it having values in the %total and %self columns. Here the main entry here have been bolded for connivence.</p></div>
<div class="para"><p>So if we look at the last slice. The primary entry would be Array#each_index. It takes 0.18% of the total process time and it is only called once. It is called from Object#make_random_array which is only called once. It's children are Kernal.rand which is called by it all 500 its times that it was call in this action and Arry#[]= which was called 500 times by Array#each_index and once by some other entry.</p></div>
<div class="paragraph"><p>As you can see the calls have been separated into slices, no longer is the order determined by process time but instead from hierarchy. Each slice profiles a primary entry, with the primary entry&#8217;s parents being shown above itself and it&#8217;s children found below. A primary entry can be ascertained by it having values in the %total and %self columns. Here the main entry here have been bolded for connivence.</p></div>
<div class="paragraph"><p>So if we look at the last slice. The primary entry would be Array#each_index. It takes 0.18% of the total process time and it is only called once. It is called from Object#make_random_array which is only called once. It&#8217;s children are Kernal.rand which is called by it all 500 its times that it was call in this action and Arry#[]= which was called 500 times by Array#each_index and once by some other entry.</p></div>
<h3 id="_tree_files">5.4. Tree Files</h3>
<div class="para"><p>It's pointless trying to represent a tree file textually so here's a few pretty pictures of it's usefulness</p></div>
<div class="para"><div class="title">KCachegrind Graph</div><p><span class="image">
<div class="paragraph"><p>It&#8217;s pointless trying to represent a tree file textually so here&#8217;s a few pretty pictures of it&#8217;s usefulness</p></div>
<div class="paragraph"><div class="title">KCachegrind Graph</div><p><span class="image">
<img src="images/kgraph.png" alt="Graph created by KCachegrind" title="Graph created by KCachegrind" />
</span></p></div>
<div class="para"><div class="title">KCachegrind List</div><p><span class="image">
<div class="paragraph"><div class="title">KCachegrind List</div><p><span class="image">
<img src="images/klist.png" alt="List created by KCachegrind" title="List created by KCachegrind" />
</span></p></div>
<div class="para"><p>#TODO Add a bit more information to this.</p></div>
<div class="paragraph"><p>#TODO Add a bit more information to this.</p></div>
</div>
<h2 id="_getting_to_the_point_of_all_of_this">6. Getting to the Point of all of this</h2>
<div class="sectionbody">
<div class="para"><p>Now I know all of this is a bit dry and academic. But it's a very powerful tool when you know how to leverage it properly. Which we are going to take a look at in our next section</p></div>
<div class="paragraph"><p>Now I know all of this is a bit dry and academic. But it&#8217;s a very powerful tool when you know how to leverage it properly. Which we are going to take a look at in our next section</p></div>
</div>
<h2 id="_real_life_example">7. Real Life Example</h2>
<div class="sectionbody">
<h3 id="_the_setup">7.1. The setup</h3>
<div class="para"><p>So I have been building this application for the last month and feel pretty good about the ruby code. I'm readying it for beta testers when I discover to my shock that with less then twenty people it starts to crash. It's a pretty simple Ecommerce site so I'm very confused by what I'm seeing. On running looking through my log files I find to my shock that the lowest time for a page run is running around 240 ms. My database finds aren't the problems so I'm lost as to what is happening to cause all this. Lets run a benchmark.</p></div>
<div class="paragraph"><p>So I have been building this application for the last month and feel pretty good about the ruby code. I&#8217;m readying it for beta testers when I discover to my shock that with less then twenty people it starts to crash. It&#8217;s a pretty simple Ecommerce site so I&#8217;m very confused by what I&#8217;m seeing. On running looking through my log files I find to my shock that the lowest time for a page run is running around 240 ms. My database finds aren&#8217;t the problems so I&#8217;m lost as to what is happening to cause all this. Lets run a benchmark.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -757,28 +745,27 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_homepage
get <span style="color: #FF0000">'/'</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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="listingblock">
<div class="title">Example: Output</div>
<div class="title">Output</div>
<div class="content">
<pre><tt>HomepageTest#test_homepage (115 ms warmup)
process_time: 591 ms
memory: 3052.90 KB
objects: 59471</tt></pre>
</div></div>
<div class="para"><p>Obviously something is very very wrong here. 3052.90 Kb to load my minimal homepage. For Comparison for another site running well I get this for my homepage test.</p></div>
<div class="paragraph"><p>Obviously something is very very wrong here. 3052.90 Kb to load my minimal homepage. For Comparison for another site running well I get this for my homepage test.</p></div>
<div class="listingblock">
<div class="title">Example: Default</div>
<div class="title">Default</div>
<div class="content">
<pre><tt>HomepageTest#test_homepage (19 ms warmup)
process_time: 26 ms
memory: 298.79 KB
objects: 1917</tt></pre>
</div></div>
<div class="para"><p>that over a factor of ten difference. Lets look at our flat process time file to see if anything pops out at us.</p></div>
<div class="paragraph"><p>that over a factor of ten difference. Lets look at our flat process time file to see if anything pops out at us.</p></div>
<div class="listingblock">
<div class="title">Example: Process time</div>
<div class="title">Process time</div>
<div class="content">
<pre><tt>20.73 0.39 0.12 0.00 0.27 420 Pathname#cleanpath_aggressive
17.07 0.14 0.10 0.00 0.04 3186 Pathname#chop_basename
@@ -790,10 +777,10 @@ http://www.gnu.org/software/src-highlite -->
2.66 0.09 0.02 0.00 0.07 480 Array#each
2.46 0.01 0.01 0.00 0.00 3606 Regexp#to_s</tt></pre>
</div></div>
<div class="para"><p>Yes indeed we seem to have found the problem. Pathname#cleanpath_aggressive is taking nearly a quarter our process time and Pathname#chop_basename another 17%. From here I do a few more benchmarks to make sure that these processes are slowing down the other pages. They are so now I know what I must do. <strong>If we can get rid of or shorten these processes we can make our pages run much quicker</strong>.</p></div>
<div class="para"><p>Now both of these are main ruby processes so are goal right now is to find out what other process is calling them. Glancing at our Graph file I see that #cleanpath is calling #cleanpath_aggressive. #cleanpath is being called by String#gsub and from there some html template errors. But my page seems to be rendering fine. why would it be calling template errors. I'm decide to check my object flat file to see if I can find any more information.</p></div>
<div class="paragraph"><p>Yes indeed we seem to have found the problem. Pathname#cleanpath_aggressive is taking nearly a quarter our process time and Pathname#chop_basename another 17%. From here I do a few more benchmarks to make sure that these processes are slowing down the other pages. They are so now I know what I must do. <strong>If we can get rid of or shorten these processes we can make our pages run much quicker</strong>.</p></div>
<div class="paragraph"><p>Now both of these are main ruby processes so are goal right now is to find out what other process is calling them. Glancing at our Graph file I see that #cleanpath is calling #cleanpath_aggressive. #cleanpath is being called by String#gsub and from there some html template errors. But my page seems to be rendering fine. why would it be calling template errors. I&#8217;m decide to check my object flat file to see if I can find any more information.</p></div>
<div class="listingblock">
<div class="title">Example: Objects Created</div>
<div class="title">Objects Created</div>
<div class="content">
<pre><tt>20.74 34800.00 12324.00 0.00 22476.00 420 Pathname#cleanpath_aggressive
16.79 18696.00 9978.00 0.00 8718.00 3186 Pathname#chop_basename
@@ -801,9 +788,9 @@ http://www.gnu.org/software/src-highlite -->
8.51 41964.00 5059.00 0.00 36905.00 1386 String#gsub
6.07 3606.00 3606.00 0.00 0.00 3606 Regexp#to_s</tt></pre>
</div></div>
<div class="para"><p>nope nothing new here. Lets look at memory usage</p></div>
<div class="paragraph"><p>nope nothing new here. Lets look at memory usage</p></div>
<div class="listingblock">
<div class="title">Example: Memory Consuption</div>
<div class="title">Memory Consuption</div>
<div class="content">
<pre><tt> 40.17 1706.80 1223.70 0.00 483.10 3186 Pathname#chop_basename
14.92 454.47 454.47 0.00 0.00 3606 Regexp#to_s
@@ -811,7 +798,7 @@ http://www.gnu.org/software/src-highlite -->
5.08 231.19 154.73 0.00 76.46 420 Pathname#prepend_prefix
2.34 71.35 71.35 0.00 0.00 1265 String#initialize_copy</tt></pre>
</div></div>
<div class="para"><p>Ok so it seems Regexp#to_s is the second costliest process. At this point I try to figure out what could be calling a regular expression cause I very rarely use them. Going over my standard layout I discover at the top.</p></div>
<div class="paragraph"><p>Ok so it seems Regexp#to_s is the second costliest process. At this point I try to figure out what could be calling a regular expression cause I very rarely use them. Going over my standard layout I discover at the top.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -819,9 +806,8 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>&lt;%if request.env["HTTP_USER_AGENT"].match(/Opera/)%&gt;
&lt;%= stylesheet_link_tag "opera" %&gt;
&lt;% end %&gt;
</tt></pre></div></div>
<div class="para"><p>That's wrong. I mistakenly am using a search function for a simple compare function. Lets fix that.</p></div>
&lt;% end %&gt;</tt></pre></div></div>
<div class="paragraph"><p>That&#8217;s wrong. I mistakenly am using a search function for a simple compare function. Lets fix that.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -829,25 +815,24 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>&lt;%if request.env["HTTP_USER_AGENT"] =~ /Opera/%&gt;
&lt;%= stylesheet_link_tag "opera" %&gt;
&lt;% end %&gt;
</tt></pre></div></div>
<div class="para"><p>I'll now try my test again.</p></div>
&lt;% end %&gt;</tt></pre></div></div>
<div class="paragraph"><p>I&#8217;ll now try my test again.</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>process_time: 75 ms
memory: 519.95 KB
objects: 6537</tt></pre>
</div></div>
<div class="para"><p>Much better. The problem has been solved. Now I should have realized earlier due to the String#gsub that my problem had to be with reqexp serch function but such knowledge comes with time. Looking through the mass output data is a skill.</p></div>
<div class="paragraph"><p>Much better. The problem has been solved. Now I should have realized earlier due to the String#gsub that my problem had to be with reqexp serch function but such knowledge comes with time. Looking through the mass output data is a skill.</p></div>
</div>
<h2 id="_get_yourself_a_game_plan">8. Get Yourself a Game Plan</h2>
<div class="sectionbody">
<div class="para"><p>You end up dealing with a large amount of data whenever you profile an application. It's crucial to use a rigorous approach to analyzing your application's performance else fail miserably in a vortex of numbers. This leads us to -</p></div>
<div class="paragraph"><p>You end up dealing with a large amount of data whenever you profile an application. It&#8217;s crucial to use a rigorous approach to analyzing your application&#8217;s performance else fail miserably in a vortex of numbers. This leads us to -</p></div>
<h3 id="_the_analysis_process">8.1. The Analysis Process</h3>
<div class="para"><p>Im going to give an example methodology for conducting your benchmarking and profiling on an application. It is based on your typical scientific method.</p></div>
<div class="para"><p>For something as complex as Benchmarking you need to take any methodology with a grain of salt but there are some basic strictures that you can depend on.</p></div>
<div class="para"><p>Formulate a question you need to answer which is simple, tests the smallest measurable thing possible, and is exact. This is typically the hardest part of the experiment. From there some steps that you should follow are.</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>Im going to give an example methodology for conducting your benchmarking and profiling on an application. It is based on your typical scientific method.</p></div>
<div class="paragraph"><p>For something as complex as Benchmarking you need to take any methodology with a grain of salt but there are some basic strictures that you can depend on.</p></div>
<div class="paragraph"><p>Formulate a question you need to answer which is simple, tests the smallest measurable thing possible, and is exact. This is typically the hardest part of the experiment. From there some steps that you should follow are.</p></div>
<div class="ulist"><ul>
<li>
<p>
Develop a set of variables and processes to measure in order to answer this question!
@@ -857,10 +842,10 @@ Develop a set of variables and processes to measure in order to answer this ques
<p>
Profile based on the question and variables. Key problems to avoid when designing this experiment are:
</p>
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
Confounding: Test one thing at a time, keep everything the same so you don't poison the data with uncontrolled processes.
Confounding: Test one thing at a time, keep everything the same so you don&#8217;t poison the data with uncontrolled processes.
</p>
</li>
<li>
@@ -906,18 +891,18 @@ Perform the analysis on the results and determine where to go from there.
</p>
</li>
</ul></div>
<div class="para"><p>Note: Even though we are using the typical scientific method; developing a hypothesis is not always useful in terms of profiling.</p></div>
<div class="paragraph"><p>Note: Even though we are using the typical scientific method; developing a hypothesis is not always useful in terms of profiling.</p></div>
</div>
<h2 id="_other_profiling_tools">9. Other Profiling Tools</h2>
<div class="sectionbody">
<div class="para"><p>There are a lot of great profiling tools out there. Some free, some not so free. This is a sort list detailing some of them.</p></div>
<div class="paragraph"><p>There are a lot of great profiling tools out there. Some free, some not so free. This is a sort list detailing some of them.</p></div>
<h3 id="_httperf">9.1. httperf</h3>
<div class="para"><p><a href="http://www.hpl.hp.com/research/linux/httperf/">http://www.hpl.hp.com/research/linux/httperf/</a></p></div>
<div class="para"><p>A necessary tool in your arsenal. Very useful for load testing your website.</p></div>
<div class="para"><p>#TODO write and link to a short article on how to use httperf. Anybody have a good tutorial availble.</p></div>
<div class="paragraph"><p><a href="http://www.hpl.hp.com/research/linux/httperf/">http://www.hpl.hp.com/research/linux/httperf/</a></p></div>
<div class="paragraph"><p>A necessary tool in your arsenal. Very useful for load testing your website.</p></div>
<div class="paragraph"><p>#TODO write and link to a short article on how to use httperf. Anybody have a good tutorial availble.</p></div>
<h3 id="_rails_analyzer">9.2. Rails Analyzer</h3>
<div class="para"><p>The Rails Analyzer project contains a collection of tools for Rails. It's open source and pretty speedy. It's not being actively worked on but is still contains some very useful tools.</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>The Rails Analyzer project contains a collection of tools for Rails. It&#8217;s open source and pretty speedy. It&#8217;s not being actively worked on but is still contains some very useful tools.</p></div>
<div class="ulist"><ul>
<li>
<p>
The Production Log Analyzer examines Rails log files and gives back a report. It also includes action_grep which will give you all log results for a particular action.
@@ -939,24 +924,24 @@ The SQL Dependency Grapher allows you to visualize the frequency of table depend
</p>
</li>
</ul></div>
<div class="para"><p>Their project homepage can be found at <a href="http://rails-analyzer.rubyforge.org/">http://rails-analyzer.rubyforge.org/</a></p></div>
<div class="para"><p>The one major caveat is that it needs your log to be in a different format from how rails sets it up specifically SyslogLogger.</p></div>
<div class="paragraph"><p>Their project homepage can be found at <a href="http://rails-analyzer.rubyforge.org/">http://rails-analyzer.rubyforge.org/</a></p></div>
<div class="paragraph"><p>The one major caveat is that it needs your log to be in a different format from how rails sets it up specifically SyslogLogger.</p></div>
<h4 id="_sysloglogger">9.2.1. SyslogLogger</h4>
<div class="para"><p>SyslogLogger is a Logger work-alike that logs via syslog instead of to a file. You can add SyslogLogger to your Rails production environment to aggregate logs between multiple machines.</p></div>
<div class="para"><p>More information can be found out at <a href="http://rails-analyzer.rubyforge.org/hacks/classes/SyslogLogger.html">http://rails-analyzer.rubyforge.org/hacks/classes/SyslogLogger.html</a></p></div>
<div class="para"><p>If you don't have access to your machines root system or just want something a bit easier to implement there is also a module developed by Geoffrey Grosenbach</p></div>
<div class="paragraph"><p>SyslogLogger is a Logger work-alike that logs via syslog instead of to a file. You can add SyslogLogger to your Rails production environment to aggregate logs between multiple machines.</p></div>
<div class="paragraph"><p>More information can be found out at <a href="http://rails-analyzer.rubyforge.org/hacks/classes/SyslogLogger.html">http://rails-analyzer.rubyforge.org/hacks/classes/SyslogLogger.html</a></p></div>
<div class="paragraph"><p>If you don&#8217;t have access to your machines root system or just want something a bit easier to implement there is also a module developed by Geoffrey Grosenbach</p></div>
<h4 id="_a_hodel_3000_compliant_logger_for_the_rest_of_us">9.2.2. A Hodel 3000 Compliant Logger for the Rest of Us</h4>
<div class="para"><p>Directions taken from
<div class="paragraph"><p>Directions taken from
<a href="http://topfunky.net/svn/plugins/hodel_3000_compliant_logger/lib/hodel_3000_compliant_logger.rb">link to module file</a></p></div>
<div class="para"><p>Just put the module in your lib directory and add this to your environment.rb in it's config portion.</p></div>
<div class="paragraph"><p>Just put the module in your lib directory and add this to your environment.rb in it&#8217;s config portion.</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>require 'hodel_3000_compliant_logger'
config.logger = Hodel3000CompliantLogger.new(config.log_path)</tt></pre>
</div></div>
<div class="para"><p>It's that simple. Your log output on restart should look like this.</p></div>
<div class="paragraph"><p>It&#8217;s that simple. Your log output on restart should look like this.</p></div>
<div class="listingblock">
<div class="title">Example: Hodel 3000 Example</div>
<div class="title">Hodel 3000 Example</div>
<div class="content">
<pre><tt>Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
Parameters: {"action"=&gt;"shipping", "controller"=&gt;"checkout"}
@@ -985,20 +970,20 @@ Jul 15 11:45:43 matthew-bergmans-macbook-pro-15 rails[16207]:
Completed in 0.37297 (2 reqs/sec) | Rendering: 0.02971 (7%) | DB: 0.01697 (4%) | 200 OK [https://secure.jeffbooks/checkout/shipping]</tt></pre>
</div></div>
<h3 id="_palmist">9.3. Palmist</h3>
<div class="para"><p>An open source mysql query analyzer. Full featured and easy to work with. Also requires Hodel 3000
<div class="paragraph"><p>An open source mysql query analyzer. Full featured and easy to work with. Also requires Hodel 3000
<a href="http://www.flyingmachinestudios.com/projects/">http://www.flyingmachinestudios.com/projects/</a></p></div>
<h3 id="_new_relic">9.4. New Relic</h3>
<div class="para"><p><a href="http://www.newrelic.com/">http://www.newrelic.com/</a></p></div>
<div class="para"><p>Pretty nifty performance tools, pricey though. They do have a basic free
<div class="paragraph"><p><a href="http://www.newrelic.com/">http://www.newrelic.com/</a></p></div>
<div class="paragraph"><p>Pretty nifty performance tools, pricey though. They do have a basic free
service both for when in development and when you put your application into production. Very simple installation and signup.</p></div>
<div class="para"><p>#TODO more in-depth without being like an advertisement.</p></div>
<div class="paragraph"><p>#TODO more in-depth without being like an advertisement.</p></div>
<h4 id="_manage">9.4.1. Manage</h4>
<div class="para"><p>Like new relic a production monitoring tool.</p></div>
<div class="paragraph"><p>Like new relic a production monitoring tool.</p></div>
</div>
<h2 id="_changelog">10. Changelog</h2>
<div class="sectionbody">
<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/4">Lighthouse ticket</a></p></div>
<div class="ilist"><ul>
<div class="paragraph"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/4">Lighthouse ticket</a></p></div>
<div class="ulist"><ul>
<li>
<p>
October 17, 2008: First revision by Pratik

View File

@@ -229,16 +229,16 @@ ul#navMain {
<h1>Caching with Rails: An overview</h1>
<div id="preamble">
<div class="sectionbody">
<div class="para"><p>Everyone caches. This guide will teach you what you need to know about
<div class="paragraph"><p>Everyone caches. This guide will teach you what you need to know about
avoiding that expensive round-trip to your database and returning what you
need to return to those hungry web clients in the shortest time possible.</p></div>
</div>
</div>
<h2 id="_basic_caching">1. Basic Caching</h2>
<div class="sectionbody">
<div class="para"><p>This is an introduction to the three types of caching techniques that Rails
<div class="paragraph"><p>This is an introduction to the three types of caching techniques that Rails
provides by default without the use of any third party plugins.</p></div>
<div class="para"><p>To get started make sure <tt>config.action_controller.perform_caching</tt> is set
<div class="paragraph"><p>To get started make sure <tt>config.action_controller.perform_caching</tt> is set
to <tt>true</tt> for your environment. This flag is normally set in the
corresponding config/environments/*.rb and caching is disabled by default
there for development and test, and enabled for production.</p></div>
@@ -247,16 +247,15 @@ there for development and test, and enabled for production.</p></div>
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>config<span style="color: #990000">.</span>action_controller<span style="color: #990000">.</span>perform_caching <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
</tt></pre></div></div>
<pre><tt>config<span style="color: #990000">.</span>action_controller<span style="color: #990000">.</span>perform_caching <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span></tt></pre></div></div>
<h3 id="_page_caching">1.1. Page Caching</h3>
<div class="para"><p>Page caching is a Rails mechanism which allows the request for a generated
<div class="paragraph"><p>Page caching is a Rails mechanism which allows the request for a generated
page to be fulfilled by the webserver, without ever having to go through the
Rails stack at all. Obviously, this is super-fast. Unfortunately, it can't be
Rails stack at all. Obviously, this is super-fast. Unfortunately, it can&#8217;t be
applied to every situation (such as pages that need authentication) and since
the webserver is literally just serving a file from the filesystem, cache
expiration is an issue that needs to be dealt with.</p></div>
<div class="para"><p>So, how do you enable this super-fast cache behavior? Simple, let's say you
<div class="paragraph"><p>So, how do you enable this super-fast cache behavior? Simple, let&#8217;s say you
have a controller called ProductsController and a <em>list</em> action that lists all
the products</p></div>
<div class="listingblock">
@@ -270,23 +269,22 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> index<span style="color: #990000">;</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>The first time anyone requests products/index, Rails will generate a file
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The first time anyone requests products/index, Rails will generate a file
called <tt>index.html</tt> and the webserver will then look for that file before it
passes the next request for products/index to your Rails application.</p></div>
<div class="para"><p>By default, the page cache directory is set to Rails.public_path (which is
<div class="paragraph"><p>By default, the page cache directory is set to Rails.public_path (which is
usually set to <tt>RAILS_ROOT + "/public"</tt>) and this can be configured by
changing the configuration setting <tt>config.action_controller.page_cache_directory</tt>.
Changing the default from /public helps avoid naming conflicts, since you may
want to put other static html in /public, but changing this will require web
server reconfiguration to let the web server know where to serve the cached
files from.</p></div>
<div class="para"><p>The Page Caching mechanism will automatically add a <tt>.html</tt> exxtension to
<div class="paragraph"><p>The Page Caching mechanism will automatically add a <tt>.html</tt> exxtension to
requests for pages that do not have an extension to make it easy for the
webserver to find those pages and this can be configured by changing the
configuration setting <tt>config.action_controller.page_cache_extension</tt>.</p></div>
<div class="para"><p>In order to expire this page when a new product is added we could extend our
<div class="paragraph"><p>In order to expire this page when a new product is added we could extend our
example controler like this:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
@@ -303,20 +301,19 @@ http://www.gnu.org/software/src-highlite -->
expire_page <span style="color: #990000">:</span>action <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>list
<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>If you want a more complicated expiration scheme, you can use cache sweepers
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>If you want a more complicated expiration scheme, you can use cache sweepers
to expire cached objects when things change. This is covered in the section on Sweepers.</p></div>
<h3 id="_action_caching">1.2. Action Caching</h3>
<div class="para"><p>One of the issues with Page Caching is that you cannot use it for pages that
<div class="paragraph"><p>One of the issues with Page Caching is that you cannot use it for pages that
require to restrict access somehow. This is where Action Caching comes in.
Action Caching works like Page Caching except for the fact that the incoming
web request does go from the webserver to the Rails stack and Action Pack so
that before filters can be run on it before the cache is served, so that
authentication and other restrictions can be used while still serving the
result of the output from a cached copy.</p></div>
<div class="para"><p>Clearing the cache works in the exact same way as with Page Caching.</p></div>
<div class="para"><p>Let's say you only wanted authenticated users to edit or create a Product
<div class="paragraph"><p>Clearing the cache works in the exact same way as with Page Caching.</p></div>
<div class="paragraph"><p>Let&#8217;s say you only wanted authenticated users to edit or create a Product
object, but still cache those pages:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
@@ -338,28 +335,27 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> edit<span style="color: #990000">;</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>And you can also use <tt>:if</tt> (or <tt>:unless</tt>) to pass a Proc that specifies when the
action should be cached. Also, you can use <tt>:layout &#8658; false</tt> to cache without
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>And you can also use <tt>:if</tt> (or <tt>:unless</tt>) to pass a Proc that specifies when the
action should be cached. Also, you can use <tt>:layout =&gt; false</tt> to cache without
layout so that dynamic information in the layout such as logged in user info
or the number of items in the cart can be left uncached. This feature is
available as of Rails 2.2.</p></div>
<div class="para"><p>[More: more examples? Walk-through of Action Caching from request to response?
<div class="paragraph"><p>[More: more examples? Walk-through of Action Caching from request to response?
Description of Rake tasks to clear cached files? Show example of
subdomain caching? Talk about :cache_path, :if and assing blocks/Procs
to expire_action?]</p></div>
<h3 id="_fragment_caching">1.3. Fragment Caching</h3>
<div class="para"><p>Life would be perfect if we could get away with caching the entire contents of
<div class="paragraph"><p>Life would be perfect if we could get away with caching the entire contents of
a page or action and serving it out to the world. Unfortunately, dynamic web
applications usually build pages with a variety of components not all of which
have the same caching characteristics. In order to address such a dynamically
created page where different parts of the page need to be cached and expired
differently Rails provides a mechanism called Fragment Caching.</p></div>
<div class="para"><p>Fragment Caching allows a fragment of view logic to be wrapped in a cache
<div class="paragraph"><p>Fragment Caching allows a fragment of view logic to be wrapped in a cache
block and served out of the cache store when the next request comes in.</p></div>
<div class="para"><p>As an example, if you wanted to show all the orders placed on your website
in real time and didn't want to cache that part of the page, but did want
<div class="paragraph"><p>As an example, if you wanted to show all the orders placed on your website
in real time and didn&#8217;t want to cache that part of the page, but did want
to cache the part of the page which lists all products available, you
could use this piece of code:</p></div>
<div class="listingblock">
@@ -376,9 +372,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="color: #FF0000">&lt;% Product.find(:all).each do |p| %&gt;</span>
<span style="color: #FF0000">&lt;%= link_to p.name, product_url(p) %&gt;</span>
<span style="color: #FF0000">&lt;% end %&gt;</span>
<span style="color: #FF0000">&lt;% end %&gt;</span>
</tt></pre></div></div>
<div class="para"><p>The cache block in our example will bind to the action that called it and is
<span style="color: #FF0000">&lt;% end %&gt;</span></tt></pre></div></div>
<div class="paragraph"><p>The cache block in our example will bind to the action that called it and is
written out to the same place as the Action Cache, which means that if you
want to cache multiple fragments per action, you should provide an <tt>action_suffix</tt> to the cache call:</p></div>
<div class="listingblock">
@@ -387,17 +382,15 @@ by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #FF0000">&lt;% cache(:action =&gt;</span> <span style="color: #FF0000">'recent'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action_suffix <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'all_products'</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">%&gt;</span>
All available products<span style="color: #990000">:</span>
</tt></pre></div></div>
<div class="para"><p>and you can expire it using the <tt>expire_fragment</tt> method, like so:</p></div>
All available products<span style="color: #990000">:</span></tt></pre></div></div>
<div class="paragraph"><p>and you can expire it using the <tt>expire_fragment</tt> method, like so:</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>expire_fragment<span style="color: #990000">(:</span>controller <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'products'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'recent'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action_suffix <span style="color: #990000">=&gt;</span> 'all_products<span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>If you don't want the cache block to bind to the action that called it, You can
<pre><tt>expire_fragment<span style="color: #990000">(:</span>controller <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'products'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'recent'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action_suffix <span style="color: #990000">=&gt;</span> 'all_products<span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>If you don&#8217;t want the cache block to bind to the action that called it, You can
also use globally keyed fragments by calling the cache method with a key, like
so:</p></div>
<div class="listingblock">
@@ -406,25 +399,23 @@ by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #FF0000">&lt;% cache(:key =&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">'all_available_products'</span><span style="color: #990000">,</span> <span style="color: #009900">@latest_product</span><span style="color: #990000">.</span>created_at<span style="color: #990000">].</span>join<span style="color: #990000">(</span><span style="color: #FF0000">':'</span><span style="color: #990000">))</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">%&gt;</span>
All available products<span style="color: #990000">:</span>
</tt></pre></div></div>
<div class="para"><p>This fragment is then available to all actions in the ProductsController using
All available products<span style="color: #990000">:</span></tt></pre></div></div>
<div class="paragraph"><p>This fragment is then available to all actions in the ProductsController using
the key and can be expired the same way:</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>expire_fragment<span style="color: #990000">(:</span>key <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">'all_available_products'</span><span style="color: #990000">,</span> <span style="color: #009900">@latest_product</span><span style="color: #990000">.</span>created_at<span style="color: #990000">].</span>join<span style="color: #990000">(</span><span style="color: #FF0000">':'</span><span style="color: #990000">))</span>
</tt></pre></div></div>
<pre><tt>expire_fragment<span style="color: #990000">(:</span>key <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">'all_available_products'</span><span style="color: #990000">,</span> <span style="color: #009900">@latest_product</span><span style="color: #990000">.</span>created_at<span style="color: #990000">].</span>join<span style="color: #990000">(</span><span style="color: #FF0000">':'</span><span style="color: #990000">))</span></tt></pre></div></div>
<h3 id="_sweepers">1.4. Sweepers</h3>
<div class="para"><p>Cache sweeping is a mechanism which allows you to get around having a ton of
<div class="paragraph"><p>Cache sweeping is a mechanism which allows you to get around having a ton of
expire_{page,action,fragment} calls in your code by moving all the work
required to expire cached content into a <tt>ActionController::Caching::Sweeper</tt>
class that is an Observer and looks for changes to an object via callbacks,
and when a change occurs it expires the caches associated with that object n
an around or after filter.</p></div>
<div class="para"><p>Continuing with our Product controller example, we could rewrite it with a
<div class="paragraph"><p>Continuing with our Product controller example, we could rewrite it with a
sweeper such as the following:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
@@ -432,19 +423,19 @@ 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> StoreSweeper <span style="color: #990000">&lt;</span> ActionController<span style="color: #990000">::</span>Caching<span style="color: #990000">::</span>Sweeper
observe Product <span style="font-style: italic"><span style="color: #9A1900"># This sweeper is going to keep an eye on the Post model</span></span>
observe Product <span style="font-style: italic"><span style="color: #9A1900"># This sweeper is going to keep an eye on the Product model</span></span>
<span style="font-style: italic"><span style="color: #9A1900"># If our sweeper detects that a Post was created call this</span></span>
<span style="font-style: italic"><span style="color: #9A1900"># If our sweeper detects that a Product was created call this</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> after_create<span style="color: #990000">(</span>product<span style="color: #990000">)</span>
expire_cache_for<span style="color: #990000">(</span>product<span style="color: #990000">)</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
<span style="font-style: italic"><span style="color: #9A1900"># If our sweeper detects that a Post was updated call this</span></span>
<span style="font-style: italic"><span style="color: #9A1900"># If our sweeper detects that a Product was updated call this</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> after_update<span style="color: #990000">(</span>product<span style="color: #990000">)</span>
expire_cache_for<span style="color: #990000">(</span>product<span style="color: #990000">)</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
<span style="font-style: italic"><span style="color: #9A1900"># If our sweeper detects that a Post was deleted call this</span></span>
<span style="font-style: italic"><span style="color: #9A1900"># If our sweeper detects that a Product was deleted call this</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> after_destroy<span style="color: #990000">(</span>product<span style="color: #990000">)</span>
expire_cache_for<span style="color: #990000">(</span>product<span style="color: #990000">)</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
@@ -457,9 +448,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-style: italic"><span style="color: #9A1900"># Expire a fragment</span></span>
expire_fragment<span style="color: #990000">(:</span>controller <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'#{record}'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'recent'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action_suffix <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'all_products'</span><span style="color: #990000">)</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>Then we add it to our controller to tell it to call the sweeper when certain
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Then we add it to our controller to tell it to call the sweeper when certain
actions are called. So, if we wanted to expire the cached content for the
list and edit actions when the create action was called, we could do the
following:</p></div>
@@ -484,14 +474,13 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> edit<span style="color: #990000">;</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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<h3 id="_sql_caching">1.5. SQL Caching</h3>
<div class="para"><p>Query caching is a Rails feature that caches the result set returned by each
<div class="paragraph"><p>Query caching is a Rails feature that caches the result set returned by each
query so that if Rails encounters the same query again for that request, it
will used the cached result set as opposed to running the query against the
database again.</p></div>
<div class="para"><p>For example:</p></div>
<div class="paragraph"><p>For example:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -521,21 +510,20 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> edit<span style="color: #990000">;</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>In the <em>list</em> action above, the result set returned by the first
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>In the <em>list</em> action above, the result set returned by the first
Product.find(:all) will be cached and will be used to avoid querying the
database again the second time that finder is called.</p></div>
<div class="para"><p>Query caches are created at the start of an action and destroyed at the end of
<div class="paragraph"><p>Query caches are created at the start of an action and destroyed at the end of
that action and thus persist only for the duration of the action.</p></div>
<h3 id="_cache_stores">1.6. Cache stores</h3>
<div class="para"><p>Rails provides different stores for the cached data for action and fragment
<div class="paragraph"><p>Rails provides different stores for the cached data for action and fragment
caches. Page caches are always stored on disk.</p></div>
<div class="para"><p>The cache stores provided include:</p></div>
<div class="para"><p>1) Memory store: Cached data is stored in the memory allocated to the Rails
<div class="paragraph"><p>The cache stores provided include:</p></div>
<div class="paragraph"><p>1) Memory store: Cached data is stored in the memory allocated to the Rails
process, which is fine for WEBrick and for FCGI (if you
don't care that each FCGI process holds its own fragment
store). It's not suitable for CGI as the process is thrown
don&#8217;t care that each FCGI process holds its own fragment
store). It&#8217;s not suitable for CGI as the process is thrown
away at the end of each request. It can potentially also
take up a lot of memory since each process keeps all the
caches in memory.</p></div>
@@ -544,9 +532,8 @@ caches. Page caches are always stored on disk.</p></div>
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>memory_store
</tt></pre></div></div>
<div class="para"><p>2) File store: Cached data is stored on the disk, this is the default store
<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>memory_store</tt></pre></div></div>
<div class="paragraph"><p>2) File store: Cached data is stored on the disk, this is the default store
and the default path for this store is: /tmp/cache. Works
well for all types of environments and allows all processes
running from the same application directory to access the
@@ -556,9 +543,8 @@ http://www.gnu.org/software/src-highlite -->
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>file_store<span style="color: #990000">,</span> <span style="color: #FF0000">"/path/to/cache/directory"</span>
</tt></pre></div></div>
<div class="para"><p>3) DRb store: Cached data is stored in a separate shared DRb process that all
<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>file_store<span style="color: #990000">,</span> <span style="color: #FF0000">"/path/to/cache/directory"</span></tt></pre></div></div>
<div class="paragraph"><p>3) DRb store: Cached data is stored in a separate shared DRb process that all
servers communicate with. This works for all environments and
only keeps one cache around for all processes, but requires
that you run and manage a separate DRb process.</p></div>
@@ -567,41 +553,38 @@ http://www.gnu.org/software/src-highlite -->
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>drb_store<span style="color: #990000">,</span> <span style="color: #FF0000">"druby://localhost:9192"</span>
</tt></pre></div></div>
<div class="para"><p>4) MemCached store: Works like DRbStore, but uses Danga's MemCache instead.
<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>drb_store<span style="color: #990000">,</span> <span style="color: #FF0000">"druby://localhost:9192"</span></tt></pre></div></div>
<div class="paragraph"><p>4) MemCached store: Works like DRbStore, but uses Danga&#8217;s MemCache instead.
Rails uses the bundled memcached-client gem by default.</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>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>mem_cache_store<span style="color: #990000">,</span> <span style="color: #FF0000">"localhost"</span>
</tt></pre></div></div>
<div class="para"><p>5) Custom store: You can define your own cache store (new in Rails 2.1)</p></div>
<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>mem_cache_store<span style="color: #990000">,</span> <span style="color: #FF0000">"localhost"</span></tt></pre></div></div>
<div class="paragraph"><p>5) Custom store: You can define your own cache store (new in Rails 2.1)</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>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> MyOwnStore<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"parameter"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p><tt>Note: config.cache_store can be used in place of
<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> MyOwnStore<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"parameter"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p><tt>Note: config.cache_store can be used in place of
ActionController::Base.cache_store in your Rails::Initializer.run block in
environment.rb</tt></p></div>
</div>
<h2 id="_conditional_get_support">2. Conditional GET support</h2>
<div class="sectionbody">
<div class="para"><p>Conditional GETs are a facility of the HTTP spec that provide a way for web
<div class="paragraph"><p>Conditional GETs are a facility of the HTTP spec that provide a way for web
servers to tell browsers that the response to a GET request hasnt changed
since the last request and can be safely pulled from the browser cache.</p></div>
<div class="para"><p>They work by using the HTTP_IF_NONE_MATCH and HTTP_IF_MODIFIED_SINCE headers to
<div class="paragraph"><p>They work by using the HTTP_IF_NONE_MATCH and HTTP_IF_MODIFIED_SINCE headers to
pass back and forth both a unique content identifier and the timestamp of when
the content was last changed. If the browser makes a request where the content
identifier (etag) or last modified since timestamp matches the servers version
then the server only needs to send back an empty response with a not modified
status.</p></div>
<div class="para"><p>It is the servers (i.e. our) responsibility to look for a last modified
<div class="paragraph"><p>It is the servers (i.e. our) responsibility to look for a last modified
timestamp and the if-none-match header and determine whether or not to send
back the full response. With conditional-get support in rails this is a pretty
easy task:</p></div>
@@ -627,9 +610,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-style: italic"><span style="color: #9A1900"># anything. The default render checks for this using the parameters</span></span>
<span style="font-style: italic"><span style="color: #9A1900"># used in the previous call to stale? and will automatically send a</span></span>
<span style="font-style: italic"><span style="color: #9A1900"># :not_modified. So that's it, you're done.</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>If you dont have any special response processing and are using the default
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>If you dont have any special response processing and are using the default
rendering mechanism (i.e. youre not using respond_to or calling render
yourself) then youve got an easy helper in fresh_when:</p></div>
<div class="listingblock">
@@ -646,15 +628,14 @@ http://www.gnu.org/software/src-highlite -->
<span style="color: #009900">@product</span> <span style="color: #990000">=</span> Product<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
fresh_when <span style="color: #990000">:</span>last_modified <span style="color: #990000">=&gt;</span> <span style="color: #009900">@product</span><span style="color: #990000">.</span>published_at<span style="color: #990000">.</span>utc<span style="color: #990000">,</span> <span style="color: #990000">:</span>etag <span style="color: #990000">=&gt;</span> <span style="color: #009900">@article</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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
</div>
<h2 id="_advanced_caching">3. Advanced Caching</h2>
<div class="sectionbody">
<div class="para"><p>Along with the built-in mechanisms outlined above, a number of excellent
<div class="paragraph"><p>Along with the built-in mechanisms outlined above, a number of excellent
plugins exist to help with finer grained control over caching. These include
Chris Wanstrath's excellent cache_fu plugin (more info here:
<a href="http://errtheblog.com/posts/57-kickin-ass-w-cachefu">http://errtheblog.com/posts/57-kickin-ass-w-cachefu</a>) and Evan Weaver's
Chris Wanstrath&#8217;s excellent cache_fu plugin (more info here:
<a href="http://errtheblog.com/posts/57-kickin-ass-w-cachefu">http://errtheblog.com/posts/57-kickin-ass-w-cachefu</a>) and Evan Weaver&#8217;s
interlock plugin (more info here:
<a href="http://blog.evanweaver.com/articles/2007/12/13/better-rails-caching/">http://blog.evanweaver.com/articles/2007/12/13/better-rails-caching/</a>). Both
of these plugins play nice with memcached and are a must-see for anyone

View File

@@ -208,6 +208,18 @@ ul#navMain {
<li><a href="#_generate">generate</a></li>
<li><a href="#_console">console</a></li>
<li><a href="#_dbconsole">dbconsole</a></li>
<li><a href="#_plugin">plugin</a></li>
<li><a href="#_runner">runner</a></li>
<li><a href="#_destroy">destroy</a></li>
<li><a href="#_about">about</a></li>
</ul>
</li>
</ol>
@@ -217,8 +229,8 @@ ul#navMain {
<h1>A Guide to The Rails Command Line</h1>
<div id="preamble">
<div class="sectionbody">
<div class="para"><p>Rails comes with every command line tool you'll need to</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>Rails comes with every command line tool you&#8217;ll need to</p></div>
<div class="ulist"><ul>
<li>
<p>
Create a Rails application
@@ -245,14 +257,14 @@ Profile and benchmark your new creation
</p>
</li>
</ul></div>
<div class="para"><p>&#8230; and much, much more! (Buy now!)</p></div>
<div class="para"><p>This tutorial assumes you have basic Rails knowledge from reading the Getting Started with Rails Guide.</p></div>
<div class="paragraph"><p>... and much, much more! (Buy now!)</p></div>
<div class="paragraph"><p>This tutorial assumes you have basic Rails knowledge from reading the Getting Started with Rails Guide.</p></div>
</div>
</div>
<h2 id="_command_line_basics">1. Command Line Basics</h2>
<div class="sectionbody">
<div class="para"><p>There are a few commands that are absolutely critical to your everyday usage of Rails. In the order of how much you'll probably use them are:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>There are a few commands that are absolutely critical to your everyday usage of Rails. In the order of how much you&#8217;ll probably use them are:</p></div>
<div class="ulist"><ul>
<li>
<p>
console
@@ -279,9 +291,9 @@ rails
</p>
</li>
</ul></div>
<div class="para"><p>Let's create a simple Rails application to step through each of these commands in context.</p></div>
<div class="paragraph"><p>Let&#8217;s create a simple Rails application to step through each of these commands in context.</p></div>
<h3 id="_rails">1.1. rails</h3>
<div class="para"><p>The first thing we'll want to do is create a new Rails application by running the <tt>rails</tt> command after installing Rails.</p></div>
<div class="paragraph"><p>The first thing we&#8217;ll want to do is create a new Rails application by running the <tt>rails</tt> command after installing Rails.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -305,9 +317,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="color: #990000">...</span>
create log/production<span style="color: #990000">.</span>log
create log/development<span style="color: #990000">.</span>log
create log/test<span style="color: #990000">.</span>log
</tt></pre></div></div>
<div class="para"><p>Rails will set you up with what seems like a huge amount of stuff for such a tiny command! You've got the entire Rails directory structure now with all the code you need to run our simple application right out of the box.</p></div>
create log/test<span style="color: #990000">.</span>log</tt></pre></div></div>
<div class="paragraph"><p>Rails will set you up with what seems like a huge amount of stuff for such a tiny command! You&#8217;ve got the entire Rails directory structure now with all the code you need to run our simple application right out of the box.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -317,16 +328,16 @@ http://www.gnu.org/software/src-highlite -->
</tr></table>
</div>
<h3 id="_server">1.2. server</h3>
<div class="para"><p>Let's try it! The <tt>server</tt> command launches a small web server written in Ruby named WEBrick which was also installed when you installed Rails. You'll use this any time you want to view your work through a web browser.</p></div>
<div class="paragraph"><p>Let&#8217;s try it! The <tt>server</tt> command launches a small web server named WEBrick which comes bundled with Ruby. You&#8217;ll use this any time you want to view your work through a web browser.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
<td class="content">WEBrick isn't your only option for serving Rails. We'll get to that in a later section. [XXX: which section]</td>
<td class="content">WEBrick isn&#8217;t your only option for serving Rails. We&#8217;ll get to that in a later section. [XXX: which section]</td>
</tr></table>
</div>
<div class="para"><p>Here we'll flex our <tt>server</tt> command, which without any prodding of any kind will run our new shiny Rails app:</p></div>
<div class="paragraph"><p>Here we&#8217;ll flex our <tt>server</tt> command, which without any prodding of any kind will run our new shiny Rails app:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -339,12 +350,11 @@ $ <span style="color: #990000">.</span>/script/server
<span style="color: #990000">=&gt;</span> Ctrl-C to shutdown server<span style="color: #990000">;</span> call with --help <span style="font-weight: bold"><span style="color: #0000FF">for</span></span> options
<span style="color: #990000">[</span><span style="color: #993399">2008</span>-<span style="color: #993399">11</span>-<span style="color: #993399">04</span> <span style="color: #993399">10</span><span style="color: #990000">:</span><span style="color: #993399">11</span><span style="color: #990000">:</span><span style="color: #993399">38</span><span style="color: #990000">]</span> INFO WEBrick <span style="color: #993399">1.3</span><span style="color: #990000">.</span><span style="color: #993399">1</span>
<span style="color: #990000">[</span><span style="color: #993399">2008</span>-<span style="color: #993399">11</span>-<span style="color: #993399">04</span> <span style="color: #993399">10</span><span style="color: #990000">:</span><span style="color: #993399">11</span><span style="color: #990000">:</span><span style="color: #993399">38</span><span style="color: #990000">]</span> INFO ruby <span style="color: #993399">1.8</span><span style="color: #990000">.</span><span style="color: #993399">5</span> <span style="color: #990000">(</span><span style="color: #993399">2006</span>-<span style="color: #993399">12</span>-<span style="color: #993399">04</span><span style="color: #990000">)</span> <span style="color: #990000">[</span>i486-linux<span style="color: #990000">]</span>
<span style="color: #990000">[</span><span style="color: #993399">2008</span>-<span style="color: #993399">11</span>-<span style="color: #993399">04</span> <span style="color: #993399">10</span><span style="color: #990000">:</span><span style="color: #993399">11</span><span style="color: #990000">:</span><span style="color: #993399">38</span><span style="color: #990000">]</span> INFO WEBrick<span style="color: #990000">::</span>HTTPServer<span style="font-style: italic"><span style="color: #9A1900">#start: pid=18994 port=3000</span></span>
</tt></pre></div></div>
<div class="para"><p>WHOA. With just three commands we whipped up a Rails server listening on port 3000. Go! Go right now to your browser and go to <a href="http://localhost:3000">http://localhost:3000</a>. I'll wait.</p></div>
<div class="para"><p>See? Cool! It doesn't do much yet, but we'll change that.</p></div>
<span style="color: #990000">[</span><span style="color: #993399">2008</span>-<span style="color: #993399">11</span>-<span style="color: #993399">04</span> <span style="color: #993399">10</span><span style="color: #990000">:</span><span style="color: #993399">11</span><span style="color: #990000">:</span><span style="color: #993399">38</span><span style="color: #990000">]</span> INFO WEBrick<span style="color: #990000">::</span>HTTPServer<span style="font-style: italic"><span style="color: #9A1900">#start: pid=18994 port=3000</span></span></tt></pre></div></div>
<div class="paragraph"><p>WHOA. With just three commands we whipped up a Rails server listening on port 3000. Go! Go right now to your browser and go to <a href="http://localhost:3000">http://localhost:3000</a>. I&#8217;ll wait.</p></div>
<div class="paragraph"><p>See? Cool! It doesn&#8217;t do much yet, but we&#8217;ll change that.</p></div>
<h3 id="_generate">1.3. generate</h3>
<div class="para"><p>The <tt>generate</tt> command uses templates to create a whole lot of things. You can always find out what's available by running <tt>generate</tt> by itself. Let's do that:</p></div>
<div class="paragraph"><p>The <tt>generate</tt> command uses templates to create a whole lot of things. You can always find out what&#8217;s available by running <tt>generate</tt> by itself. Let&#8217;s do that:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -360,24 +370,23 @@ Installed Generators
Builtin<span style="color: #990000">:</span> controller<span style="color: #990000">,</span> integration_test<span style="color: #990000">,</span> mailer<span style="color: #990000">,</span> migration<span style="color: #990000">,</span> model<span style="color: #990000">,</span> observer<span style="color: #990000">,</span> performance_test<span style="color: #990000">,</span> plugin<span style="color: #990000">,</span> resource<span style="color: #990000">,</span> scaffold<span style="color: #990000">,</span> session_migration
<span style="color: #990000">...</span>
<span style="color: #990000">...</span>
</tt></pre></div></div>
<span style="color: #990000">...</span></tt></pre></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
<td class="content">You can install more generators through generator gems, portions of plugins you'll undoubtedly install, and you can even create your own!</td>
<td class="content">You can install more generators through generator gems, portions of plugins you&#8217;ll undoubtedly install, and you can even create your own!</td>
</tr></table>
</div>
<div class="para"><p>Using generators will save you a large amount of time by writing <strong>boilerplate code</strong> for you &#8212; necessary for the darn thing to work, but not necessary for you to spend time writing. That's what we have computers for, right?</p></div>
<div class="para"><p>Let's make our own controller with the controller generator. But what command should we use? Let's ask the generator:</p></div>
<div class="paragraph"><p>Using generators will save you a large amount of time by writing <strong>boilerplate code</strong> for you&#8201;&#8212;&#8201;necessary for the darn thing to work, but not necessary for you to spend time writing. That&#8217;s what we have computers for, right?</p></div>
<div class="paragraph"><p>Let&#8217;s make our own controller with the controller generator. But what command should we use? Let&#8217;s ask the generator:</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
<td class="content">All Rails console utilities have help text. For commands that require a lot of input to run correctly, you can try the command without any parameters (like <tt>rails</tt> or <tt>./script/generate</tt>). For others, you can try adding <tt>&#8212;help</tt> or <tt>-h</tt> to the end, as in <tt>./script/server &#8212;help</tt>.</td>
<td class="content">All Rails console utilities have help text. As with most *NIX utilities, you can try adding <tt>--help</tt> or <tt>-h</tt> to the end, for example <tt>./script/server --help</tt>.</td>
</tr></table>
</div>
<div class="listingblock">
@@ -407,9 +416,8 @@ Modules Example<span style="color: #990000">:</span>
Controller<span style="color: #990000">:</span> app/controllers/admin/credit_card_controller<span style="color: #990000">.</span>rb
Views<span style="color: #990000">:</span> app/views/admin/credit_card/debit<span style="color: #990000">.</span>html<span style="color: #990000">.</span>erb <span style="color: #990000">[...]</span>
Helper<span style="color: #990000">:</span> app/helpers/admin/credit_card_helper<span style="color: #990000">.</span>rb
Test<span style="color: #990000">:</span> test/functional/admin/credit_card_controller_test<span style="color: #990000">.</span>rb
</tt></pre></div></div>
<div class="para"><p>Ah, the controller generator is expecting parameters in the form of <tt>generate controller ControllerName action1 action2</tt>. Let's make a <tt>Greetings</tt> controller with an action of <strong>hello</strong>, which will say something nice to us.</p></div>
Test<span style="color: #990000">:</span> test/functional/admin/credit_card_controller_test<span style="color: #990000">.</span>rb</tt></pre></div></div>
<div class="paragraph"><p>Ah, the controller generator is expecting parameters in the form of <tt>generate controller ControllerName action1 action2</tt>. Let&#8217;s make a <tt>Greetings</tt> controller with an action of <strong>hello</strong>, which will say something nice to us.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -423,10 +431,9 @@ http://www.gnu.org/software/src-highlite -->
create app/controllers/greetings_controller<span style="color: #990000">.</span>rb
create test/functional/greetings_controller_test<span style="color: #990000">.</span>rb
create app/helpers/greetings_helper<span style="color: #990000">.</span>rb
create app/views/greetings/hello<span style="color: #990000">.</span>html<span style="color: #990000">.</span>erb
</tt></pre></div></div>
<div class="para"><p>Look there! Now what all did this generate? It looks like it made sure a bunch of directories were in our application, and created a controller file, a functional test file, a helper for the view, and a view file.</p></div>
<div class="para"><p>Let's check out the controller and modify it a little (in <tt>app/controllers/greeting_controller.rb</tt>):</p></div>
create app/views/greetings/hello<span style="color: #990000">.</span>html<span style="color: #990000">.</span>erb</tt></pre></div></div>
<div class="paragraph"><p>Look there! Now what all did this generate? It looks like it made sure a bunch of directories were in our application, and created a controller file, a functional test file, a helper for the view, and a view file.</p></div>
<div class="paragraph"><p>Let&#8217;s check out the controller and modify it a little (in <tt>app/controllers/greeting_controller.rb</tt>):</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -437,27 +444,24 @@ http://www.gnu.org/software/src-highlite -->
<span style="color: #009900">@message</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"Hello, how are you today? I am exuberant!"</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>Then the view, to display our nice message (in <tt>app/views/greeting/hello.html.erb</tt>):</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Then the view, to display our nice message (in <tt>app/views/greeting/hello.html.erb</tt>):</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">&lt;h1&gt;</span></span>A Greeting for You!<span style="font-weight: bold"><span style="color: #0000FF">&lt;/h1&gt;</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">&lt;p&gt;</span></span>&lt;%= @message %&gt;<span style="font-weight: bold"><span style="color: #0000FF">&lt;/p&gt;</span></span>
</tt></pre></div></div>
<div class="para"><p>Deal. Go check it out in your browser. Fire up your server. Remember? <tt>./script/server</tt> at the root of your Rails application should do it.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">&lt;p&gt;</span></span>&lt;%= @message %&gt;<span style="font-weight: bold"><span style="color: #0000FF">&lt;/p&gt;</span></span></tt></pre></div></div>
<div class="paragraph"><p>Deal. Go check it out in your browser. Fire up your server. Remember? <tt>./script/server</tt> at the root of your Rails application should do it.</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="color: #990000">.</span>/script/server
<span style="color: #990000">=&gt;</span> Booting WEBrick<span style="color: #990000">...</span>
</tt></pre></div></div>
<div class="para"><p>The URL will be <tt>http://localhost:3000/greetings/hello</tt>. I'll wait for you to be suitably impressed.</p></div>
<span style="color: #990000">=&gt;</span> Booting WEBrick<span style="color: #990000">...</span></tt></pre></div></div>
<div class="paragraph"><p>The URL will be <tt>http://localhost:3000/greetings/hello</tt>. I&#8217;ll wait for you to be suitably impressed.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -466,7 +470,7 @@ http://www.gnu.org/software/src-highlite -->
<td class="content">With a normal, plain-old Rails application, your URLs will generally follow the pattern of <a href="http://(host)/(controller)/(action">http://(host)/(controller)/(action</a>), and a URL like <a href="http://(host)/(controller">http://(host)/(controller</a>) will hit the <strong>index</strong> action of that controller.</td>
</tr></table>
</div>
<div class="para"><p>"What about data, though?", you ask over a cup of coffee. Rails comes with a generator for data models too. Can you guess its generator name?</p></div>
<div class="paragraph"><p>"What about data, though?", you ask over a cup of coffee. Rails comes with a generator for data models too. Can you guess its generator name?</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -488,26 +492,52 @@ Examples<span style="color: #990000">:</span>
`<span style="color: #990000">.</span>/script/generate model post title<span style="color: #990000">:</span>string body<span style="color: #990000">:</span>text published<span style="color: #990000">:</span>boolean`
creates a Post model with a string title<span style="color: #990000">,</span> text body<span style="color: #990000">,</span> and published flag<span style="color: #990000">.</span>
</tt></pre></div></div>
<div class="para"><p>Let's set up a simple model called "HighScore" that will keep track of our highest score on video games we play. Then we'll wire up our controller and view to modify and list our scores.</p></div>
creates a Post model with a string title<span style="color: #990000">,</span> text body<span style="color: #990000">,</span> and published flag<span style="color: #990000">.</span></tt></pre></div></div>
<div class="paragraph"><p>But instead of generating a model directly (which we&#8217;ll be doing later), let&#8217;s set up a scaffold. A <strong>scaffold</strong> in Rails is a full set of model, database migration for that model, controller to manipulate it, views to view and manipulate the data, and a test suite for each of the above.</p></div>
<div class="paragraph"><p>Let&#8217;s set up a simple resource called "HighScore" that will keep track of our highest score on video games we play.</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="color: #990000">.</span>/script/generate model HighScore id<span style="color: #990000">:</span>integer game<span style="color: #990000">:</span>string score<span style="color: #990000">:</span>integer
exists app/models<span style="color: #990000">/</span>
exists test/unit<span style="color: #990000">/</span>
exists test/fixtures<span style="color: #990000">/</span>
create app/models/high_score<span style="color: #990000">.</span>rb
create test/unit/high_score_test<span style="color: #990000">.</span>rb
create test/fixtures/high_scores<span style="color: #990000">.</span>yml
create db/migrate
create db/migrate<span style="color: #990000">/</span>20081126032945_create_high_scores<span style="color: #990000">.</span>rb
</tt></pre></div></div>
<div class="para"><p>Taking it from the top, we have the <strong>models</strong> directory, where all of your data models live. <strong>test/unit</strong>, where all the unit tests live (gasp! &#8212; unit tests!), fixtures for those tests, a test, the <strong>migrate</strong> directory, where the database-modifying migrations live, and a migration to create the <tt>high_scores</tt> table with the right fields.</p></div>
<div class="para"><p>The migration requires that we <strong>migrate</strong>, that is, run some Ruby code (living in that <tt>20081126032945_create_high_scores.rb</tt>) to modify the schema of our database. Which database? The sqlite3 database that Rails will create for you when we run the <tt>rake db:migrate</tt> command. We'll talk more about Rake in-depth in a little while.</p></div>
<pre><tt>$ <span style="color: #990000">.</span>/script/generate scaffold HighScore game<span style="color: #990000">:</span>string score<span style="color: #990000">:</span>integer
exists app/models<span style="color: #990000">/</span>
exists app/controllers<span style="color: #990000">/</span>
exists app/helpers<span style="color: #990000">/</span>
create app/views/high_scores
create app/views/layouts<span style="color: #990000">/</span>
exists test/functional<span style="color: #990000">/</span>
create test/unit<span style="color: #990000">/</span>
create public/stylesheets<span style="color: #990000">/</span>
create app/views/high_scores/index<span style="color: #990000">.</span>html<span style="color: #990000">.</span>erb
create app/views/high_scores/show<span style="color: #990000">.</span>html<span style="color: #990000">.</span>erb
create app/views/high_scores/new<span style="color: #990000">.</span>html<span style="color: #990000">.</span>erb
create app/views/high_scores/edit<span style="color: #990000">.</span>html<span style="color: #990000">.</span>erb
create app/views/layouts/high_scores<span style="color: #990000">.</span>html<span style="color: #990000">.</span>erb
create public/stylesheets/scaffold<span style="color: #990000">.</span>css
create app/controllers/high_scores_controller<span style="color: #990000">.</span>rb
create test/functional/high_scores_controller_test<span style="color: #990000">.</span>rb
create app/helpers/high_scores_helper<span style="color: #990000">.</span>rb
route map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>high_scores
dependency model
exists app/models<span style="color: #990000">/</span>
exists test/unit<span style="color: #990000">/</span>
create test/fixtures<span style="color: #990000">/</span>
create app/models/high_score<span style="color: #990000">.</span>rb
create test/unit/high_score_test<span style="color: #990000">.</span>rb
create test/fixtures/high_scores<span style="color: #990000">.</span>yml
exists db/migrate
create db/migrate<span style="color: #990000">/</span>20081217071914_create_high_scores<span style="color: #990000">.</span>rb</tt></pre></div></div>
<div class="paragraph"><p>Taking it from the top - the generator checks that there exist the directories for models, controllers, helpers, layouts, functional and unit tests, stylesheets, creates the views, controller, model and database migration for HighScore (creating the <tt>high_scores</tt> table and fields), takes care of the route for the <strong>resource</strong>, and new tests for everything.</p></div>
<div class="paragraph"><p>The migration requires that we <strong>migrate</strong>, that is, run some Ruby code (living in that <tt>20081217071914_create_high_scores.rb</tt>) to modify the schema of our database. Which database? The sqlite3 database that Rails will create for you when we run the <tt>rake db:migrate</tt> command. We&#8217;ll talk more about Rake in-depth in a little while.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
<td class="content">Hey. Install the sqlite3-ruby gem while you&#8217;re at it. <tt>gem install sqlite3-ruby</tt></td>
</tr></table>
</div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -518,37 +548,94 @@ http://www.gnu.org/software/src-highlite -->
<span style="color: #990000">==</span> CreateHighScores<span style="color: #990000">:</span> migrating <span style="color: #990000">===============================================</span>
-- create_table<span style="color: #990000">(:</span>high_scores<span style="color: #990000">)</span>
-<span style="color: #990000">&gt;</span> <span style="color: #993399">0</span><span style="color: #990000">.</span>0070s
<span style="color: #990000">==</span> CreateHighScores<span style="color: #990000">:</span> migrated <span style="color: #990000">(</span><span style="color: #993399">0</span><span style="color: #990000">.</span>0077s<span style="color: #990000">)</span> <span style="color: #990000">======================================</span>
</tt></pre></div></div>
<span style="color: #990000">==</span> CreateHighScores<span style="color: #990000">:</span> migrated <span style="color: #990000">(</span><span style="color: #993399">0</span><span style="color: #990000">.</span>0077s<span style="color: #990000">)</span> <span style="color: #990000">======================================</span></tt></pre></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
<td class="content">Let's talk about unit tests. Unit tests are code that tests and makes assertions about code. In unit testing, we take a little part of code, say a method of a model, and test its inputs and outputs. Unit tests are your friend. The sooner you make peace with the fact that your quality of life will drastically increase when you unit test your code, the better. Seriously. We'll make one in a moment.</td>
<td class="content">Let&#8217;s talk about unit tests. Unit tests are code that tests and makes assertions about code. In unit testing, we take a little part of code, say a method of a model, and test its inputs and outputs. Unit tests are your friend. The sooner you make peace with the fact that your quality of life will drastically increase when you unit test your code, the better. Seriously. We&#8217;ll make one in a moment.</td>
</tr></table>
</div>
<div class="para"><p>Yo! Let's shove a small table into our greeting controller and view, listing our sweet scores.</p></div>
<div class="paragraph"><p>Let&#8217;s see the interface Rails created for us. ./script/server; <a href="http://localhost:3000/high_scores">http://localhost:3000/high_scores</a></p></div>
<div class="paragraph"><p>We can create new high scores (55,160 on Space Invaders!)</p></div>
<h3 id="_console">1.4. console</h3>
<div class="paragraph"><p>The <tt>console</tt> command lets you interact with your Rails application from the command line. On the underside, <tt>script/console</tt> uses IRB, so if you&#8217;ve ever used it, you&#8217;ll be right at home. This is useful for testing out quick ideas with code and changing data server-side without touching the website.</p></div>
<h3 id="_dbconsole">1.5. dbconsole</h3>
<div class="paragraph"><p><tt>dbconsole</tt> figures out which database you&#8217;re using and drops you into whichever command line interface you would use with it (and figures out the command line parameters to give to it, too!). It supports MySQL, PostgreSQL, SQLite and SQLite3.</p></div>
<h3 id="_plugin">1.6. plugin</h3>
<div class="paragraph"><p>The <tt>plugin</tt> command simplifies plugin management; think a miniature version of the Gem utility. Let&#8217;s walk through installing a plugin. You can call the sub-command <strong>discover</strong>, which sifts through repositories looking for plugins, or call <strong>source</strong> to add a specific repository of plugins, or you can specify the plugin location directly.</p></div>
<div class="paragraph"><p>Let&#8217;s say you&#8217;re creating a website for a client who wants a small accounting system. Every event having to do with money must be logged, and must never be deleted. Wouldn&#8217;t it be great if we could override the behavior of a model to never actually take its record out of the database, but <strong>instead</strong>, just set a field?</p></div>
<div class="paragraph"><p>There is such a thing! The plugin we&#8217;re installing is called "acts_as_paranoid", and it lets models implement a "deleted_at" column that gets set when you call destroy. Later, when calling find, the plugin will tack on a database check to filter out "deleted" things.</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> GreetingController <span style="color: #990000">&lt;</span> ApplicationController
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> hello
<span style="font-weight: bold"><span style="color: #0000FF">if</span></span> request<span style="color: #990000">.</span>post?
score <span style="color: #990000">=</span> HighScore<span style="color: #990000">.</span>new<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>high_score<span style="color: #990000">])</span>
<span style="font-weight: bold"><span style="color: #0000FF">if</span></span> score<span style="color: #990000">.</span>save
flash<span style="color: #990000">[:</span>notice<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="color: #FF0000">"New score posted!"</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>
<span style="color: #009900">@scores</span> <span style="color: #990000">=</span> HighScore<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">)</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>XXX: Go with scaffolding instead, modifying greeting controller for high scores seems dumb.</p></div>
<pre><tt>$ <span style="color: #990000">.</span>/script/plugin install http<span style="color: #990000">:</span>//svn<span style="color: #990000">.</span>techno-weenie<span style="color: #990000">.</span>net/projects/plugins/acts_as_paranoid
<span style="color: #990000">+</span> <span style="color: #990000">.</span>/CHANGELOG
<span style="color: #990000">+</span> <span style="color: #990000">.</span>/MIT-LICENSE
<span style="color: #990000">...</span>
<span style="color: #990000">...</span></tt></pre></div></div>
<h3 id="_runner">1.7. runner</h3>
<div class="paragraph"><p><tt>runner</tt> runs Ruby code in the context of Rails non-interactively. For instance:</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="color: #990000">.</span>/script/runner <span style="color: #FF0000">"Model.long_running_method"</span></tt></pre></div></div>
<h3 id="_destroy">1.8. destroy</h3>
<div class="paragraph"><p>Think of <tt>destroy</tt> as the opposite of <tt>generate</tt>. It&#8217;ll figure out what generate did, and undo it. Believe you-me, the creation of this tutorial used this command many times!</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="color: #990000">.</span>/script/generate model Oops
exists app/models<span style="color: #990000">/</span>
exists test/unit<span style="color: #990000">/</span>
exists test/fixtures<span style="color: #990000">/</span>
create app/models/oops<span style="color: #990000">.</span>rb
create test/unit/oops_test<span style="color: #990000">.</span>rb
create test/fixtures/oops<span style="color: #990000">.</span>yml
exists db/migrate
create db/migrate<span style="color: #990000">/</span>20081221040817_create_oops<span style="color: #990000">.</span>rb
$ <span style="color: #990000">.</span>/script/destroy model Oops
notempty db/migrate
notempty db
rm db/migrate<span style="color: #990000">/</span>20081221040817_create_oops<span style="color: #990000">.</span>rb
rm test/fixtures/oops<span style="color: #990000">.</span>yml
rm test/unit/oops_test<span style="color: #990000">.</span>rb
rm app/models/oops<span style="color: #990000">.</span>rb
notempty test/fixtures
notempty <span style="font-weight: bold"><span style="color: #0000FF">test</span></span>
notempty test/unit
notempty <span style="font-weight: bold"><span style="color: #0000FF">test</span></span>
notempty app/models
notempty app</tt></pre></div></div>
<h3 id="_about">1.9. about</h3>
<div class="paragraph"><p>Check it: Version numbers for Ruby, RubyGems, Rails, the Rails subcomponents, your application&#8217;s folder, the current Rails environment name, your app&#8217;s database adapter, and schema version! <tt>about</tt> is useful when you need to ask help, check if a security patch might affect you, or when you need some stats for an existing Rails installation.</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="color: #990000">.</span>/script/about
About your application<span style="color: #FF0000">'s environment</span>
<span style="color: #FF0000">Ruby version 1.8.6 (i486-linux)</span>
<span style="color: #FF0000">RubyGems version 1.3.1</span>
<span style="color: #FF0000">Rails version 2.2.0</span>
<span style="color: #FF0000">Active Record version 2.2.0</span>
<span style="color: #FF0000">Action Pack version 2.2.0</span>
<span style="color: #FF0000">Active Resource version 2.2.0</span>
<span style="color: #FF0000">Action Mailer version 2.2.0</span>
<span style="color: #FF0000">Active Support version 2.2.0</span>
<span style="color: #FF0000">Edge Rails revision unknown</span>
<span style="color: #FF0000">Application root /home/commandsapp</span>
<span style="color: #FF0000">Environment development</span>
<span style="color: #FF0000">Database adapter sqlite3</span>
<span style="color: #FF0000">Database schema version 20081217073400</span></tt></pre></div></div>
</div>
</div>

View File

@@ -246,8 +246,8 @@ ul#navMain {
<h1>Configuring Rails Applications</h1>
<div id="preamble">
<div class="sectionbody">
<div class="para"><p>This guide covers the configuration and initialization features available to Rails applications. By referring to this guide, you will be able to:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>This guide covers the configuration and initialization features available to Rails applications. By referring to this guide, you will be able to:</p></div>
<div class="ulist"><ul>
<li>
<p>
Adjust the behavior of your Rails applications
@@ -263,7 +263,7 @@ Add additional code to be run at application start time
</div>
<h2 id="_locations_for_initialization_code">1. Locations for Initialization Code</h2>
<div class="sectionbody">
<div class="para"><p>preinitializers
<div class="paragraph"><p>preinitializers
environment.rb first
env-specific files
initializers (load_application_initializers)
@@ -278,10 +278,10 @@ after-initializer</p></div>
<h2 id="_configuring_rails_components">4. Configuring Rails Components</h2>
<div class="sectionbody">
<h3 id="_configuring_active_record">4.1. Configuring Active Record</h3>
<div class="para"><p><tt>ActiveRecord::Base</tt> includej a variety of configuration options:</p></div>
<div class="para"><p><tt>logger</tt> accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed on to any new database connections made. You can retrieve this logger by calling <tt>logger</tt> on either an ActiveRecord model class or an ActiveRecord model instance. Set to nil to disable logging.</p></div>
<div class="para"><p><tt>primary_key_prefix_type</tt> lets you adjust the naming for primary key columns. By default, Rails assumes that primary key columns are named <tt>id</tt> (and this configuration option doesn't need to be set.) There are two other choices:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p><tt>ActiveRecord::Base</tt> includej a variety of configuration options:</p></div>
<div class="paragraph"><p><tt>logger</tt> accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed on to any new database connections made. You can retrieve this logger by calling <tt>logger</tt> on either an ActiveRecord model class or an ActiveRecord model instance. Set to nil to disable logging.</p></div>
<div class="paragraph"><p><tt>primary_key_prefix_type</tt> lets you adjust the naming for primary key columns. By default, Rails assumes that primary key columns are named <tt>id</tt> (and this configuration option doesn&#8217;t need to be set.) There are two other choices:</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>:table_name</tt> would make the primary key for the Customer class <tt>customerid</tt>
@@ -293,54 +293,54 @@ after-initializer</p></div>
</p>
</li>
</ul></div>
<div class="para"><p><tt>table_name_prefix</tt> lets you set a global string to be prepended to table names. If you set this to <tt>northwest_</tt>, then the Customer class will look for <tt>northwest_customers</tt> as its table. The default is an empty string.</p></div>
<div class="para"><p><tt>table_name_suffix</tt> lets you set a global string to be appended to table names. If you set this to <tt>_northwest</tt>, then the Customer class will look for <tt>customers_northwest</tt> as its table. The default is an empty string.</p></div>
<div class="para"><p><tt>pluralize_table_names</tt> specifies whether Rails will look for singular or plural table names in the database. If set to <tt>true</tt> (the default), then the Customer class will use the <tt>customers</tt> table. If set to <tt>false</tt>, then the Customers class will use the <tt>customer</tt> table.</p></div>
<div class="para"><p><tt>colorize_logging</tt> (true by default) specifies whether or not to use ANSI color codes when logging information from ActiveRecord.</p></div>
<div class="para"><p><tt>default_timezone</tt> determines whether to use <tt>Time.local</tt> (if set to <tt>:local</tt>) or <tt>Time.utc</tt> (if set to <tt>:utc</tt>) when pulling dates and times from the database. The default is <tt>:local</tt>.</p></div>
<div class="para"><p><tt>schema_format</tt> controls the format for dumping the database schema to a file. The options are <tt>:ruby</tt> (the default) for a database-independent version that depends on migrations, or <tt>:sql</tt> for a set of (potentially database-dependent) SQL statements.</p></div>
<div class="para"><p><tt>timestamped_migrations</tt> controls whether migrations are numbered with serial integers or with timestamps. The default is <tt>true</tt>, to use timestamps, which are preferred if there are multiple developers working on the same application.</p></div>
<div class="para"><p><tt>lock_optimistically</tt> controls whether ActiveRecord will use optimistic locking. By default this is <tt>true</tt>.</p></div>
<div class="para"><p>The MySQL adapter adds one additional configuration option:</p></div>
<div class="para"><p><tt>ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans</tt> controls whether ActiveRecord will consider all <tt>tinyint(1)</tt> columns in a MySQL database to be booleans. By default this is <tt>true</tt>.</p></div>
<div class="para"><p>The schema dumper adds one additional configuration option:</p></div>
<div class="para"><p><tt>ActiveRecord::SchemaDumper.ignore_tables</tt> accepts an array of tables that should <em>not</em> be included in any generated schema file. This setting is ignored unless <tt>ActiveRecord::Base.schema_format == :ruby</tt>.</p></div>
<div class="paragraph"><p><tt>table_name_prefix</tt> lets you set a global string to be prepended to table names. If you set this to <tt>northwest_</tt>, then the Customer class will look for <tt>northwest_customers</tt> as its table. The default is an empty string.</p></div>
<div class="paragraph"><p><tt>table_name_suffix</tt> lets you set a global string to be appended to table names. If you set this to <tt>_northwest</tt>, then the Customer class will look for <tt>customers_northwest</tt> as its table. The default is an empty string.</p></div>
<div class="paragraph"><p><tt>pluralize_table_names</tt> specifies whether Rails will look for singular or plural table names in the database. If set to <tt>true</tt> (the default), then the Customer class will use the <tt>customers</tt> table. If set to <tt>false</tt>, then the Customers class will use the <tt>customer</tt> table.</p></div>
<div class="paragraph"><p><tt>colorize_logging</tt> (true by default) specifies whether or not to use ANSI color codes when logging information from ActiveRecord.</p></div>
<div class="paragraph"><p><tt>default_timezone</tt> determines whether to use <tt>Time.local</tt> (if set to <tt>:local</tt>) or <tt>Time.utc</tt> (if set to <tt>:utc</tt>) when pulling dates and times from the database. The default is <tt>:local</tt>.</p></div>
<div class="paragraph"><p><tt>schema_format</tt> controls the format for dumping the database schema to a file. The options are <tt>:ruby</tt> (the default) for a database-independent version that depends on migrations, or <tt>:sql</tt> for a set of (potentially database-dependent) SQL statements.</p></div>
<div class="paragraph"><p><tt>timestamped_migrations</tt> controls whether migrations are numbered with serial integers or with timestamps. The default is <tt>true</tt>, to use timestamps, which are preferred if there are multiple developers working on the same application.</p></div>
<div class="paragraph"><p><tt>lock_optimistically</tt> controls whether ActiveRecord will use optimistic locking. By default this is <tt>true</tt>.</p></div>
<div class="paragraph"><p>The MySQL adapter adds one additional configuration option:</p></div>
<div class="paragraph"><p><tt>ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans</tt> controls whether ActiveRecord will consider all <tt>tinyint(1)</tt> columns in a MySQL database to be booleans. By default this is <tt>true</tt>.</p></div>
<div class="paragraph"><p>The schema dumper adds one additional configuration option:</p></div>
<div class="paragraph"><p><tt>ActiveRecord::SchemaDumper.ignore_tables</tt> accepts an array of tables that should <em>not</em> be included in any generated schema file. This setting is ignored unless <tt>ActiveRecord::Base.schema_format == :ruby</tt>.</p></div>
<h3 id="_configuring_action_controller">4.2. Configuring Action Controller</h3>
<div class="para"><p>ActionController::Base includes a number of configuration settings:</p></div>
<div class="para"><p><tt>asset_host</tt> provides a string that is prepended to all of the URL-generating helpers in <tt>AssetHelper</tt>. This is designed to allow moving all javascript, CSS, and image files to a separate asset host.</p></div>
<div class="para"><p><tt>consider_all_requests_local</tt> is generally set to <tt>true</tt> during development and <tt>false</tt> during production; if it is set to <tt>true</tt>, then any error will cause detailed debugging information to be dumped in the HTTP response. For finer-grained control, set this to <tt>false</tt> and implement <tt>local_request?</tt> to specify which requests should provide debugging information on errors.</p></div>
<div class="para"><p><tt>allow_concurrency</tt> should be set to <tt>true</tt> to allow concurrent (threadsafe) action processing. Set to <tt>false</tt> by default.</p></div>
<div class="para"><p><tt>param_parsers</tt> provides an array of handlers that can extract information from incoming HTTP requests and add it to the <tt>params</tt> hash. By default, parsers for multipart forms, URL-encoded forms, XML, and JSON are active.</p></div>
<div class="para"><p><tt>default_charset</tt> specifies the default character set for all renders. The default is "utf-8".</p></div>
<div class="para"><p><tt>logger</tt> accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Controller. Set to nil to disable logging.</p></div>
<div class="para"><p><tt>resource_action_separator</tt> gives the token to be used between resources and actions when building or interpreting RESTful URLs. By default, this is "/".</p></div>
<div class="para"><p><tt>resource_path_names</tt> is a hash of default names for several RESTful actions. By default, the new action is named <tt>new</tt> and the edit action is named <tt>edit</tt>.</p></div>
<div class="para"><p><tt>request_forgery_protection_token</tt> sets the token parameter name for RequestForgery. Calling <tt>protect_from_forgery</tt> sets it to <tt>:authenticity_token</tt> by default.</p></div>
<div class="para"><p><tt>optimise_named_routes</tt> turns on some optimizations in generating the routing table. It is set to <tt>true</tt> by default.</p></div>
<div class="para"><p><tt>use_accept_header</tt> sets the rules for determining the response format. If this is set to <tt>true</tt> (the default) then <tt>respond_to</tt> and <tt>Request#format</tt> will take the Accept header into account. If it is set to false then the request format will be determined solely by examining <tt>params[:format]</tt>. If there is no <tt>format</tt> parameter, then the response format will be either HTML or Javascript depending on whether the request is an AJAX request.</p></div>
<div class="para"><p><tt>allow_forgery_protection</tt> enables or disables CSRF protection. By default this is <tt>false</tt> in test mode and <tt>true</tt> in all other modes.</p></div>
<div class="para"><p><tt>relative_url_root</tt> can be used to tell Rails that you are deploying to a subdirectory. The default is <tt>ENV[<em>RAILS_RELATIVE_URL_ROOT</em>]</tt>.</p></div>
<div class="para"><p>The caching code adds two additional settings:</p></div>
<div class="para"><p><tt>ActionController::Caching::Pages.page_cache_directory</tt> sets the directory where Rails will create cached pages for your web server. The default is <tt>Rails.public_path</tt> (which is usually set to <tt>RAILS_ROOT </tt> "/public"+).</p></div>
<div class="para"><p><tt>ActionController::Caching::Pages.page_cache_extension</tt> sets the extension to be used when generating pages for the cache (this is ignored if the incoming request already has an extension). The default is <tt>.html</tt>.</p></div>
<div class="para"><p>The dispatcher includes one setting:</p></div>
<div class="para"><p><tt>ActionController::Dispatcher.error_file_path</tt> gives the path where Rails will look for error files such as <tt>404.html</tt>. The default is <tt>Rails.public_path</tt>.</p></div>
<div class="para"><p>The Active Record session store can also be configured:</p></div>
<div class="para"><p><tt>CGI::Session::ActiveRecordStore::Session.data_column_name</tt> sets the name of the column to use to store session data. By default it is <em>data</em></p></div>
<div class="paragraph"><p>ActionController::Base includes a number of configuration settings:</p></div>
<div class="paragraph"><p><tt>asset_host</tt> provides a string that is prepended to all of the URL-generating helpers in <tt>AssetHelper</tt>. This is designed to allow moving all javascript, CSS, and image files to a separate asset host.</p></div>
<div class="paragraph"><p><tt>consider_all_requests_local</tt> is generally set to <tt>true</tt> during development and <tt>false</tt> during production; if it is set to <tt>true</tt>, then any error will cause detailed debugging information to be dumped in the HTTP response. For finer-grained control, set this to <tt>false</tt> and implement <tt>local_request?</tt> to specify which requests should provide debugging information on errors.</p></div>
<div class="paragraph"><p><tt>allow_concurrency</tt> should be set to <tt>true</tt> to allow concurrent (threadsafe) action processing. Set to <tt>false</tt> by default.</p></div>
<div class="paragraph"><p><tt>param_parsers</tt> provides an array of handlers that can extract information from incoming HTTP requests and add it to the <tt>params</tt> hash. By default, parsers for multipart forms, URL-encoded forms, XML, and JSON are active.</p></div>
<div class="paragraph"><p><tt>default_charset</tt> specifies the default character set for all renders. The default is "utf-8".</p></div>
<div class="paragraph"><p><tt>logger</tt> accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Controller. Set to nil to disable logging.</p></div>
<div class="paragraph"><p><tt>resource_action_separator</tt> gives the token to be used between resources and actions when building or interpreting RESTful URLs. By default, this is "/".</p></div>
<div class="paragraph"><p><tt>resource_path_names</tt> is a hash of default names for several RESTful actions. By default, the new action is named <tt>new</tt> and the edit action is named <tt>edit</tt>.</p></div>
<div class="paragraph"><p><tt>request_forgery_protection_token</tt> sets the token parameter name for RequestForgery. Calling <tt>protect_from_forgery</tt> sets it to <tt>:authenticity_token</tt> by default.</p></div>
<div class="paragraph"><p><tt>optimise_named_routes</tt> turns on some optimizations in generating the routing table. It is set to <tt>true</tt> by default.</p></div>
<div class="paragraph"><p><tt>use_accept_header</tt> sets the rules for determining the response format. If this is set to <tt>true</tt> (the default) then <tt>respond_to</tt> and <tt>Request#format</tt> will take the Accept header into account. If it is set to false then the request format will be determined solely by examining <tt>params[:format]</tt>. If there is no <tt>format</tt> parameter, then the response format will be either HTML or Javascript depending on whether the request is an AJAX request.</p></div>
<div class="paragraph"><p><tt>allow_forgery_protection</tt> enables or disables CSRF protection. By default this is <tt>false</tt> in test mode and <tt>true</tt> in all other modes.</p></div>
<div class="paragraph"><p><tt>relative_url_root</tt> can be used to tell Rails that you are deploying to a subdirectory. The default is <tt>ENV[<em>RAILS_RELATIVE_URL_ROOT</em>]</tt>.</p></div>
<div class="paragraph"><p>The caching code adds two additional settings:</p></div>
<div class="paragraph"><p><tt>ActionController::Caching::Pages.page_cache_directory</tt> sets the directory where Rails will create cached pages for your web server. The default is <tt>Rails.public_path</tt> (which is usually set to <tt>RAILS_ROOT + "/public"</tt>).</p></div>
<div class="paragraph"><p><tt>ActionController::Caching::Pages.page_cache_extension</tt> sets the extension to be used when generating pages for the cache (this is ignored if the incoming request already has an extension). The default is <tt>.html</tt>.</p></div>
<div class="paragraph"><p>The dispatcher includes one setting:</p></div>
<div class="paragraph"><p><tt>ActionController::Dispatcher.error_file_path</tt> gives the path where Rails will look for error files such as <tt>404.html</tt>. The default is <tt>Rails.public_path</tt>.</p></div>
<div class="paragraph"><p>The Active Record session store can also be configured:</p></div>
<div class="paragraph"><p><tt>CGI::Session::ActiveRecordStore::Session.data_column_name</tt> sets the name of the column to use to store session data. By default it is <em>data</em></p></div>
<h3 id="_configuring_action_view">4.3. Configuring Action View</h3>
<div class="para"><p>There are only a few configuration options for Action View, starting with four on <tt>ActionView::Base</tt>:</p></div>
<div class="para"><p><tt>debug_rjs</tt> specifies whether RJS responses should be wrapped in a try/catch block that alert()s the caught exception (and then re-raises it). The default is <tt>false</tt>.</p></div>
<div class="para"><p><tt>warn_cache_misses</tt> tells Rails to display a warning whenever an action results in a cache miss on your view paths. The default is <tt>false</tt>.</p></div>
<div class="para"><p></p></div>
<div class="para"><p><tt>default_form_builder</tt> tells Rails which form builder to use by default. The default is <tt>ActionView::Helpers::FormBuilder</tt>.</p></div>
<div class="para"><p>The ERB template handler supplies one additional option:</p></div>
<div class="para"><p><tt>ActionView::TemplateHandlers::ERB.erb_trim_mode</tt> gives the trim mode to be used by ERB. It defaults to <tt><em>-</em></tt>. See the <a href="http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/">ERB documentation</a> for more information.</p></div>
<div class="paragraph"><p>There are only a few configuration options for Action View, starting with four on <tt>ActionView::Base</tt>:</p></div>
<div class="paragraph"><p><tt>debug_rjs</tt> specifies whether RJS responses should be wrapped in a try/catch block that alert()s the caught exception (and then re-raises it). The default is <tt>false</tt>.</p></div>
<div class="paragraph"><p><tt>warn_cache_misses</tt> tells Rails to display a warning whenever an action results in a cache miss on your view paths. The default is <tt>false</tt>.</p></div>
<div class="paragraph"><p></p></div>
<div class="paragraph"><p><tt>default_form_builder</tt> tells Rails which form builder to use by default. The default is <tt>ActionView::Helpers::FormBuilder</tt>.</p></div>
<div class="paragraph"><p>The ERB template handler supplies one additional option:</p></div>
<div class="paragraph"><p><tt>ActionView::TemplateHandlers::ERB.erb_trim_mode</tt> gives the trim mode to be used by ERB. It defaults to <tt><em>-</em></tt>. See the <a href="http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/">ERB documentation</a> for more information.</p></div>
<h3 id="_configuring_action_mailer">4.4. Configuring Action Mailer</h3>
<div class="para"><p>There are a number of settings available on <tt>ActionMailer::Base</tt>:</p></div>
<div class="para"><p><tt>template_root</tt> gives the root folder for Action Mailer templates.</p></div>
<div class="para"><p><tt>logger</tt> accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Mailer. Set to nil to disable logging.</p></div>
<div class="para"><p><tt>smtp_settings</tt> allows detailed configuration for the <tt>:smtp</tt> delivery method. It accepts a hash of options, which can include any of these options:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>There are a number of settings available on <tt>ActionMailer::Base</tt>:</p></div>
<div class="paragraph"><p><tt>template_root</tt> gives the root folder for Action Mailer templates.</p></div>
<div class="paragraph"><p><tt>logger</tt> accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Mailer. Set to nil to disable logging.</p></div>
<div class="paragraph"><p><tt>smtp_settings</tt> allows detailed configuration for the <tt>:smtp</tt> delivery method. It accepts a hash of options, which can include any of these options:</p></div>
<div class="ulist"><ul>
<li>
<p>
&lt;tt&gt;:address&lt;/tt&gt; - Allows you to use a remote mail server. Just change it from its default "localhost" setting.
@@ -348,7 +348,7 @@ after-initializer</p></div>
</li>
<li>
<p>
&lt;tt&gt;:port&lt;/tt&gt; - On the off chance that your mail server doesn't run on port 25, you can change it.
&lt;tt&gt;:port&lt;/tt&gt; - On the off chance that your mail server doesn&#8217;t run on port 25, you can change it.
</p>
</li>
<li>
@@ -372,8 +372,8 @@ after-initializer</p></div>
</p>
</li>
</ul></div>
<div class="para"><p><tt>sendmail_settings</tt> allows detailed configuration for the <tt>sendmail</tt> delivery method. It accepts a hash of options, which can include any of these options:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p><tt>sendmail_settings</tt> allows detailed configuration for the <tt>sendmail</tt> delivery method. It accepts a hash of options, which can include any of these options:</p></div>
<div class="ulist"><ul>
<li>
<p>
&lt;tt&gt;:location&lt;/tt&gt; - The location of the sendmail executable. Defaults to &lt;tt&gt;/usr/sbin/sendmail&lt;/tt&gt;.
@@ -385,27 +385,27 @@ after-initializer</p></div>
</p>
</li>
</ul></div>
<div class="para"><p><tt>raise_delivery_errors</tt> specifies whether to raise an error if email delivery cannot be completed. It defaults to <tt>true</tt>.</p></div>
<div class="para"><p><tt>delivery_method</tt> defines the delivery method. The allowed values are &lt;tt&gt;:smtp&lt;/tt&gt; (default), &lt;tt&gt;:sendmail&lt;/tt&gt;, and &lt;tt&gt;:test&lt;/tt&gt;.</p></div>
<div class="para"><p><tt>perform_deliveries</tt> specifies whether mail will actually be delivered. By default this is <tt>true</tt>; it can be convenient to set it to <tt>false</tt> for testing.</p></div>
<div class="para"><p><tt>default_charset</tt> tells Action Mailer which character set to use for the body and for encoding the subject. It defaults to <tt>utf-8</tt>.</p></div>
<div class="para"><p><tt>default_content_type</tt> specifies the default content type used for the main part of the message. It defaults to "text/plain"</p></div>
<div class="para"><p><tt>default_mime_version</tt> is the default MIME version for the message. It defaults to <tt>1.0</tt>.</p></div>
<div class="para"><p><tt>default_implicit_parts_order</tt> - When a message is built implicitly (i.e. multiple parts are assembled from templates
<div class="paragraph"><p><tt>raise_delivery_errors</tt> specifies whether to raise an error if email delivery cannot be completed. It defaults to <tt>true</tt>.</p></div>
<div class="paragraph"><p><tt>delivery_method</tt> defines the delivery method. The allowed values are &lt;tt&gt;:smtp&lt;/tt&gt; (default), &lt;tt&gt;:sendmail&lt;/tt&gt;, and &lt;tt&gt;:test&lt;/tt&gt;.</p></div>
<div class="paragraph"><p><tt>perform_deliveries</tt> specifies whether mail will actually be delivered. By default this is <tt>true</tt>; it can be convenient to set it to <tt>false</tt> for testing.</p></div>
<div class="paragraph"><p><tt>default_charset</tt> tells Action Mailer which character set to use for the body and for encoding the subject. It defaults to <tt>utf-8</tt>.</p></div>
<div class="paragraph"><p><tt>default_content_type</tt> specifies the default content type used for the main part of the message. It defaults to "text/plain"</p></div>
<div class="paragraph"><p><tt>default_mime_version</tt> is the default MIME version for the message. It defaults to <tt>1.0</tt>.</p></div>
<div class="paragraph"><p><tt>default_implicit_parts_order</tt> - When a message is built implicitly (i.e. multiple parts are assembled from templates
which specify the content type in their filenames) this variable controls how the parts are ordered. Defaults to
&lt;tt&gt;["text/html", "text/enriched", "text/plain"]&lt;/tt&gt;. Items that appear first in the array have higher priority in the mail client
and appear last in the mime encoded message.</p></div>
<h3 id="_configuring_active_resource">4.5. Configuring Active Resource</h3>
<div class="para"><p>There is a single configuration setting available on <tt>ActiveResource::Base</tt>:</p></div>
<div class="para"><p><tt>logger</tt> accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Active Resource. Set to nil to disable logging.</p></div>
<div class="paragraph"><p>There is a single configuration setting available on <tt>ActiveResource::Base</tt>:</p></div>
<div class="paragraph"><p><tt>logger</tt> accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Active Resource. Set to nil to disable logging.</p></div>
<h3 id="_configuring_active_support">4.6. Configuring Active Support</h3>
<div class="para"><p>There are a few configuration options available in Active Support:</p></div>
<div class="para"><p><tt>ActiveSupport::BufferedLogger.silencer</tt> is set to <tt>false</tt> to disable the ability to silence logging in a block. The default is <tt>true</tt>.</p></div>
<div class="para"><p><tt>ActiveSupport::Cache::Store.logger</tt> specifies the logger to use within cache store operations.</p></div>
<div class="para"><p><tt>ActiveSupport::Logger.silencer</tt> is set to <tt>false</tt> to disable the ability to silence logging in a block. The default is <tt>true</tt>.</p></div>
<div class="paragraph"><p>There are a few configuration options available in Active Support:</p></div>
<div class="paragraph"><p><tt>ActiveSupport::BufferedLogger.silencer</tt> is set to <tt>false</tt> to disable the ability to silence logging in a block. The default is <tt>true</tt>.</p></div>
<div class="paragraph"><p><tt>ActiveSupport::Cache::Store.logger</tt> specifies the logger to use within cache store operations.</p></div>
<div class="paragraph"><p><tt>ActiveSupport::Logger.silencer</tt> is set to <tt>false</tt> to disable the ability to silence logging in a block. The default is <tt>true</tt>.</p></div>
<h3 id="_configuring_active_model">4.7. Configuring Active Model</h3>
<div class="para"><p>Active Model currently has a single configuration setting:</p></div>
<div class="para"><p>+ActiveModel::Errors.default_error_messages is an array containing all of the validation error messages.</p></div>
<div class="paragraph"><p>Active Model currently has a single configuration setting:</p></div>
<div class="paragraph"><p>+ActiveModel::Errors.default_error_messages is an array containing all of the validation error messages.</p></div>
</div>
<h2 id="_using_initializers">5. Using Initializers</h2>
<div class="sectionbody">
@@ -419,12 +419,12 @@ and appear last in the mime encoded message.</p></div>
</div>
<h2 id="_rails_environment_settings">7. Rails Environment Settings</h2>
<div class="sectionbody">
<div class="para"><p>ENV</p></div>
<div class="paragraph"><p>ENV</p></div>
</div>
<h2 id="_changelog">8. Changelog</h2>
<div class="sectionbody">
<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/28">Lighthouse ticket</a></p></div>
<div class="ilist"><ul>
<div class="paragraph"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/28">Lighthouse ticket</a></p></div>
<div class="ulist"><ul>
<li>
<p>
November 5, 2008: Rough outline by <a href="../authors.html#mgunderloy">Mike Gunderloy</a>

File diff suppressed because it is too large Load Diff

View File

@@ -280,8 +280,8 @@ ul#navMain {
<h1>Debugging Rails Applications</h1>
<div id="preamble">
<div class="sectionbody">
<div class="para"><p>This guide introduces techniques for debugging Ruby on Rails applications. By referring to this guide, you will be able to:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>This guide introduces techniques for debugging Ruby on Rails applications. By referring to this guide, you will be able to:</p></div>
<div class="ulist"><ul>
<li>
<p>
Understand the purpose of debugging
@@ -289,7 +289,7 @@ Understand the purpose of debugging
</li>
<li>
<p>
Track down problems and issues in your application that your tests aren't identifying
Track down problems and issues in your application that your tests aren&#8217;t identifying
</p>
</li>
<li>
@@ -307,8 +307,8 @@ Analyze the stack trace
</div>
<h2 id="_view_helpers_for_debugging">1. View Helpers for Debugging</h2>
<div class="sectionbody">
<div class="para"><p>One common task is to inspect the contents of a variable. In Rails, you can do this with three methods:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>One common task is to inspect the contents of a variable. In Rails, you can do this with three methods:</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>debug</tt>
@@ -326,7 +326,7 @@ Analyze the stack trace
</li>
</ul></div>
<h3 id="_debug">1.1. debug</h3>
<div class="para"><p>The <tt>debug</tt> helper will return a &lt;pre&gt;-tag that renders the object using the YAML format. This will generate human-readable data from any object. For example, if you have this code in a view:</p></div>
<div class="paragraph"><p>The <tt>debug</tt> helper will return a &lt;pre&gt;-tag that renders the object using the YAML format. This will generate human-readable data from any object. For example, if you have this code in a view:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -336,9 +336,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">&lt;p&gt;</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">&lt;b&gt;</span></span>Title:<span style="font-weight: bold"><span style="color: #0000FF">&lt;/b&gt;</span></span>
&lt;%=h @post.title %&gt;
<span style="font-weight: bold"><span style="color: #0000FF">&lt;/p&gt;</span></span>
</tt></pre></div></div>
<div class="para"><p>You'll see something like this:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">&lt;/p&gt;</span></span></tt></pre></div></div>
<div class="paragraph"><p>You&#8217;ll see something like this:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>--- !ruby/object:Post
@@ -355,7 +354,7 @@ attributes_cache: {}
Title: Rails debugging guide</tt></pre>
</div></div>
<h3 id="_to_yaml">1.2. to_yaml</h3>
<div class="para"><p>Displaying an instance variable, or any other object or method, in yaml format can be achieved this way:</p></div>
<div class="paragraph"><p>Displaying an instance variable, or any other object or method, in yaml format can be achieved this way:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -365,10 +364,9 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">&lt;p&gt;</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">&lt;b&gt;</span></span>Title:<span style="font-weight: bold"><span style="color: #0000FF">&lt;/b&gt;</span></span>
&lt;%=h @post.title %&gt;
<span style="font-weight: bold"><span style="color: #0000FF">&lt;/p&gt;</span></span>
</tt></pre></div></div>
<div class="para"><p>The <tt>to_yaml</tt> method converts the method to YAML format leaving it more readable, and then the <tt>simple_format</tt> helper is used to render each line as in the console. This is how <tt>debug</tt> method does its magic.</p></div>
<div class="para"><p>As a result of this, you will have something like this in your view:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">&lt;/p&gt;</span></span></tt></pre></div></div>
<div class="paragraph"><p>The <tt>to_yaml</tt> method converts the method to YAML format leaving it more readable, and then the <tt>simple_format</tt> helper is used to render each line as in the console. This is how <tt>debug</tt> method does its magic.</p></div>
<div class="paragraph"><p>As a result of this, you will have something like this in your view:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>--- !ruby/object:Post
@@ -384,7 +382,7 @@ attributes_cache: {}
Title: Rails debugging guide</tt></pre>
</div></div>
<h3 id="_inspect">1.3. inspect</h3>
<div class="para"><p>Another useful method for displaying object values is <tt>inspect</tt>, especially when working with arrays or hashes. This will print the object value as a string. For example:</p></div>
<div class="paragraph"><p>Another useful method for displaying object values is <tt>inspect</tt>, especially when working with arrays or hashes. This will print the object value as a string. For example:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -394,9 +392,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">&lt;p&gt;</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">&lt;b&gt;</span></span>Title:<span style="font-weight: bold"><span style="color: #0000FF">&lt;/b&gt;</span></span>
&lt;%=h @post.title %&gt;
<span style="font-weight: bold"><span style="color: #0000FF">&lt;/p&gt;</span></span>
</tt></pre></div></div>
<div class="para"><p>Will be rendered as follows:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">&lt;/p&gt;</span></span></tt></pre></div></div>
<div class="paragraph"><p>Will be rendered as follows:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>[1, 2, 3, 4, 5]
@@ -404,23 +401,21 @@ http://www.gnu.org/software/src-highlite -->
Title: Rails debugging guide</tt></pre>
</div></div>
<h3 id="_debugging_javascript">1.4. Debugging Javascript</h3>
<div class="para"><p>Rails has built-in support to debug RJS, to active it, set <tt>ActionView::Base.debug_rjs</tt> to <em>true</em>, this will specify whether RJS responses should be wrapped in a try/catch block that alert()s the caught exception (and then re-raises it).</p></div>
<div class="para"><p>To enable it, add the following in the <tt>Rails::Initializer do |config|</tt> block inside <tt>environment.rb</tt>:</p></div>
<div class="paragraph"><p>Rails has built-in support to debug RJS, to active it, set <tt>ActionView::Base.debug_rjs</tt> to <em>true</em>, this will specify whether RJS responses should be wrapped in a try/catch block that alert()s the caught exception (and then re-raises it).</p></div>
<div class="paragraph"><p>To enable it, add the following in the <tt>Rails::Initializer do |config|</tt> block inside <tt>environment.rb</tt>:</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>config<span style="color: #990000">.</span>action_view<span style="color: #990000">[:</span>debug_rjs<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
</tt></pre></div></div>
<div class="para"><p>Or, at any time, setting <tt>ActionView::Base.debug_rjs</tt> to <em>true</em>:</p></div>
<pre><tt>config<span style="color: #990000">.</span>action_view<span style="color: #990000">[:</span>debug_rjs<span style="color: #990000">]</span> <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span></tt></pre></div></div>
<div class="paragraph"><p>Or, at any time, setting <tt>ActionView::Base.debug_rjs</tt> to <em>true</em>:</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>ActionView<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>debug_rjs <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
</tt></pre></div></div>
<pre><tt>ActionView<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>debug_rjs <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span></tt></pre></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -432,27 +427,25 @@ http://www.gnu.org/software/src-highlite -->
</div>
<h2 id="_the_logger">2. The Logger</h2>
<div class="sectionbody">
<div class="para"><p>It can also be useful to save information to log files at runtime. Rails maintains a separate log file for each runtime environment.</p></div>
<div class="paragraph"><p>It can also be useful to save information to log files at runtime. Rails maintains a separate log file for each runtime environment.</p></div>
<h3 id="_what_is_the_logger">2.1. What is The Logger?</h3>
<div class="para"><p>Rails makes use of Ruby's standard <tt>logger</tt> to write log information. You can also substitute another logger such as <tt>Log4R</tt> if you wish.</p></div>
<div class="para"><p>You can specify an alternative logger in your <tt>environment.rb</tt> or any environment file:</p></div>
<div class="paragraph"><p>Rails makes use of Ruby&#8217;s standard <tt>logger</tt> to write log information. You can also substitute another logger such as <tt>Log4R</tt> if you wish.</p></div>
<div class="paragraph"><p>You can specify an alternative logger in your <tt>environment.rb</tt> or any environment file:</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>ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>logger <span style="color: #990000">=</span> Logger<span style="color: #990000">.</span>new<span style="color: #990000">(</span>STDOUT<span style="color: #990000">)</span>
ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>logger <span style="color: #990000">=</span> Log4r<span style="color: #990000">::</span>Logger<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"Application Log"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>Or in the <tt>Initializer</tt> section, add <em>any</em> of the following</p></div>
ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>logger <span style="color: #990000">=</span> Log4r<span style="color: #990000">::</span>Logger<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"Application Log"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>Or in the <tt>Initializer</tt> section, add <em>any</em> of the following</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>config<span style="color: #990000">.</span>logger <span style="color: #990000">=</span> Logger<span style="color: #990000">.</span>new<span style="color: #990000">(</span>STDOUT<span style="color: #990000">)</span>
config<span style="color: #990000">.</span>logger <span style="color: #990000">=</span> Log4r<span style="color: #990000">::</span>Logger<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"Application Log"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
config<span style="color: #990000">.</span>logger <span style="color: #990000">=</span> Log4r<span style="color: #990000">::</span>Logger<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"Application Log"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -462,17 +455,16 @@ config<span style="color: #990000">.</span>logger <span style="color: #990000">=
</tr></table>
</div>
<h3 id="_log_levels">2.2. Log Levels</h3>
<div class="para"><p>When something is logged it's printed into the corresponding log if the log level of the message is equal or higher than the configured log level. If you want to know the current log level you can call the <tt>ActiveRecord::Base.logger.level</tt> method.</p></div>
<div class="para"><p>The available log levels are: <tt>:debug</tt>, <tt>:info</tt>, <tt>:warn</tt>, <tt>:error</tt>, and <tt>:fatal</tt>, corresponding to the log level numbers from 0 up to 4 respectively. To change the default log level, use</p></div>
<div class="paragraph"><p>When something is logged it&#8217;s printed into the corresponding log if the log level of the message is equal or higher than the configured log level. If you want to know the current log level you can call the <tt>ActiveRecord::Base.logger.level</tt> method.</p></div>
<div class="paragraph"><p>The available log levels are: <tt>:debug</tt>, <tt>:info</tt>, <tt>:warn</tt>, <tt>:error</tt>, and <tt>:fatal</tt>, corresponding to the log level numbers from 0 up to 4 respectively. To change the default log level, use</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>config<span style="color: #990000">.</span>log_level <span style="color: #990000">=</span> Logger<span style="color: #990000">::</span>WARN <span style="font-style: italic"><span style="color: #9A1900"># In any environment initializer, or</span></span>
ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>logger<span style="color: #990000">.</span>level <span style="color: #990000">=</span> <span style="color: #993399">0</span> <span style="font-style: italic"><span style="color: #9A1900"># at any time</span></span>
</tt></pre></div></div>
<div class="para"><p>This is useful when you want to log under development or staging, but you don't want to flood your production log with unnecessary information.</p></div>
ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>logger<span style="color: #990000">.</span>level <span style="color: #990000">=</span> <span style="color: #993399">0</span> <span style="font-style: italic"><span style="color: #9A1900"># at any time</span></span></tt></pre></div></div>
<div class="paragraph"><p>This is useful when you want to log under development or staging, but you don&#8217;t want to flood your production log with unnecessary information.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -482,7 +474,7 @@ ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #99000
</tr></table>
</div>
<h3 id="_sending_messages">2.3. Sending Messages</h3>
<div class="para"><p>To write in the current log use the <tt>logger.(debug|info|warn|error|fatal)</tt> method from within a controller, model or mailer:</p></div>
<div class="paragraph"><p>To write in the current log use the <tt>logger.(debug|info|warn|error|fatal)</tt> method from within a controller, model or mailer:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -490,9 +482,8 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>logger<span style="color: #990000">.</span>debug <span style="color: #FF0000">"Person attributes hash: #{@person.attributes.inspect}"</span>
logger<span style="color: #990000">.</span>info <span style="color: #FF0000">"Processing the request..."</span>
logger<span style="color: #990000">.</span>fatal <span style="color: #FF0000">"Terminating application, raised unrecoverable error!!!"</span>
</tt></pre></div></div>
<div class="para"><p>Here's an example of a method instrumented with extra logging:</p></div>
logger<span style="color: #990000">.</span>fatal <span style="color: #FF0000">"Terminating application, raised unrecoverable error!!!"</span></tt></pre></div></div>
<div class="paragraph"><p>Here&#8217;s an example of a method instrumented with extra logging:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -516,9 +507,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
<span style="font-style: italic"><span style="color: #9A1900"># ...</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>Here's an example of the log generated by this method:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Here&#8217;s an example of the log generated by this method:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>Processing PostsController#create (for 127.0.0.1 at 2008-09-08 11:52:54) [POST]
@@ -537,24 +527,23 @@ The post was saved and now is the user is going to be redirected...
Redirected to #&lt;Post:0x20af760&gt;
Completed in 0.01224 (81 reqs/sec) | DB: 0.00044 (3%) | 302 Found [http://localhost/posts]</tt></pre>
</div></div>
<div class="para"><p>Adding extra logging like this makes it easy to search for unexpected or unusual behavior in your logs. If you add extra logging, be sure to make sensible use of log levels, to avoid filling your production logs with useless trivia.</p></div>
<div class="paragraph"><p>Adding extra logging like this makes it easy to search for unexpected or unusual behavior in your logs. If you add extra logging, be sure to make sensible use of log levels, to avoid filling your production logs with useless trivia.</p></div>
</div>
<h2 id="_debugging_with_ruby_debug">3. Debugging with ruby-debug</h2>
<div class="sectionbody">
<div class="para"><p>When your code is behaving in unexpected ways, you can try printing to logs or the console to diagnose the problem. Unfortunately, there are times when this sort of error tracking is not effective in finding the root cause of a problem. When you actually need to journey into your running source code, the debugger is your best companion.</p></div>
<div class="para"><p>The debugger can also help you if you want to learn about the Rails source code but don't know where to start. Just debug any request to your application and use this guide to learn how to move from the code you have written deeper into Rails code.</p></div>
<div class="paragraph"><p>When your code is behaving in unexpected ways, you can try printing to logs or the console to diagnose the problem. Unfortunately, there are times when this sort of error tracking is not effective in finding the root cause of a problem. When you actually need to journey into your running source code, the debugger is your best companion.</p></div>
<div class="paragraph"><p>The debugger can also help you if you want to learn about the Rails source code but don&#8217;t know where to start. Just debug any request to your application and use this guide to learn how to move from the code you have written deeper into Rails code.</p></div>
<h3 id="_setup">3.1. Setup</h3>
<div class="para"><p>The debugger used by Rails, <tt>ruby-debug</tt>, comes as a gem. To install it, just run:</p></div>
<div class="paragraph"><p>The debugger used by Rails, <tt>ruby-debug</tt>, comes as a gem. To install it, just run:</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>$ sudo gem install ruby-debug
</tt></pre></div></div>
<div class="para"><p>In case you want to download a particular version or get the source code, refer to the <a href="http://rubyforge.org/projects/ruby-debug/">project's page on rubyforge</a>.</p></div>
<div class="para"><p>Rails has had built-in support for ruby-debug since Rails 2.0. Inside any Rails application you can invoke the debugger by calling the <tt>debugger</tt> method.</p></div>
<div class="para"><p>Here's an example:</p></div>
<pre><tt>$ sudo gem install ruby-debug</tt></pre></div></div>
<div class="paragraph"><p>In case you want to download a particular version or get the source code, refer to the <a href="http://rubyforge.org/projects/ruby-debug/">project&#8217;s page on rubyforge</a>.</p></div>
<div class="paragraph"><p>Rails has had built-in support for ruby-debug since Rails 2.0. Inside any Rails application you can invoke the debugger by calling the <tt>debugger</tt> method.</p></div>
<div class="paragraph"><p>Here&#8217;s an example:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -565,14 +554,13 @@ http://www.gnu.org/software/src-highlite -->
debugger
<span style="color: #009900">@person</span> <span style="color: #990000">=</span> Person<span style="color: #990000">.</span>new
<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>If you see the message in the console or logs:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>If you see the message in the console or logs:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>***** Debugger requested, but was not available: Start server with --debugger to enable *****</tt></pre>
</div></div>
<div class="para"><p>Make sure you have started your web server with the option <tt>&#8212;debugger</tt>:</p></div>
<div class="paragraph"><p>Make sure you have started your web server with the option <tt>--debugger</tt>:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -582,27 +570,26 @@ http://www.gnu.org/software/src-highlite -->
<span style="color: #990000">=&gt;</span> Booting Mongrel <span style="color: #990000">(</span>use <span style="color: #FF0000">'script/server webrick'</span> to force WEBrick<span style="color: #990000">)</span>
<span style="color: #990000">=&gt;</span> Rails <span style="color: #993399">2.2</span><span style="color: #990000">.</span><span style="color: #993399">0</span> application starting on http<span style="color: #990000">://</span><span style="color: #993399">0.0</span><span style="color: #990000">.</span><span style="color: #993399">0.0</span><span style="color: #990000">:</span><span style="color: #993399">3000</span>
<span style="color: #990000">=&gt;</span> Debugger enabled
<span style="color: #990000">...</span>
</tt></pre></div></div>
<span style="color: #990000">...</span></tt></pre></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip" />
</td>
<td class="content">In development mode, you can dynamically <tt>require 'ruby-debug'</tt> instead of restarting the server, if it was started without <tt>&#8212;debugger</tt>.</td>
<td class="content">In development mode, you can dynamically &#8216;require 'ruby-debug\&#8217;<tt> instead of restarting the server, if it was started without `--debugger</tt>.</td>
</tr></table>
</div>
<div class="para"><p>In order to use Rails debugging you'll need to be running either <strong>WEBrick</strong> or <strong>Mongrel</strong>. For the moment, no alternative servers are supported.</p></div>
<div class="paragraph"><p>In order to use Rails debugging you&#8217;ll need to be running either <strong>WEBrick</strong> or <strong>Mongrel</strong>. For the moment, no alternative servers are supported.</p></div>
<h3 id="_the_shell">3.2. The Shell</h3>
<div class="para"><p>As soon as your application calls the <tt>debugger</tt> method, the debugger will be started in a debugger shell inside the terminal window where you launched your application server, and you will be placed at ruby-debug's prompt <tt>(rdb:n)</tt>. The <em>n</em> is the thread number. The prompt will also show you the next line of code that is waiting to run.</p></div>
<div class="para"><p>If you got there by a browser request, the browser tab containing the request will be hung until the debugger has finished and the trace has finished processing the entire request.</p></div>
<div class="para"><p>For example:</p></div>
<div class="paragraph"><p>As soon as your application calls the <tt>debugger</tt> method, the debugger will be started in a debugger shell inside the terminal window where you launched your application server, and you will be placed at ruby-debug&#8217;s prompt <tt>(rdb:n)</tt>. The <em>n</em> is the thread number. The prompt will also show you the next line of code that is waiting to run.</p></div>
<div class="paragraph"><p>If you got there by a browser request, the browser tab containing the request will be hung until the debugger has finished and the trace has finished processing the entire request.</p></div>
<div class="paragraph"><p>For example:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>@posts = Post.find(:all)
(rdb:7)</tt></pre>
</div></div>
<div class="para"><p>Now it's time to explore and dig into your application. A good place to start is by asking the debugger for help&#8230; so type: <tt>help</tt> (You didn't see that coming, right?)</p></div>
<div class="paragraph"><p>Now it&#8217;s time to explore and dig into your application. A good place to start is by asking the debugger for help... so type: <tt>help</tt> (You didn&#8217;t see that coming, right?)</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:7) help
@@ -621,11 +608,11 @@ continue edit frame method putl set tmate where</tt></pre>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip" />
</td>
<td class="content">To view the help menu for any command use <tt>help &lt;command-name&gt;</tt> in active debug mode. For example: <em><tt>help var</tt></em></td>
<td class="content">To view the help menu for any command use <tt>help &lt;command-name&gt;</tt> in active debug mode. For example: <em>+help var+</em></td>
</tr></table>
</div>
<div class="para"><p>The next command to learn is one of the most useful: <tt>list</tt>. You can also abbreviate ruby-debug commands by supplying just enough letters to distinguish them from other commands, so you can also use <tt>l</tt> for the <tt>list</tt> command.</p></div>
<div class="para"><p>This command shows you where you are in the code by printing 10 lines centered around the current line; the current line in this particular case is line 6 and is marked by <tt>&#8658;</tt>.</p></div>
<div class="paragraph"><p>The next command to learn is one of the most useful: <tt>list</tt>. You can also abbreviate ruby-debug commands by supplying just enough letters to distinguish them from other commands, so you can also use <tt>l</tt> for the <tt>list</tt> command.</p></div>
<div class="paragraph"><p>This command shows you where you are in the code by printing 10 lines centered around the current line; the current line in this particular case is line 6 and is marked by <tt>=&gt;</tt>.</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:7) list
@@ -641,7 +628,7 @@ continue edit frame method putl set tmate where</tt></pre>
9 format.html # index.html.erb
10 format.xml { render :xml =&gt; @posts }</tt></pre>
</div></div>
<div class="para"><p>If you repeat the <tt>list</tt> command, this time using just <tt>l</tt>, the next ten lines of the file will be printed out.</p></div>
<div class="paragraph"><p>If you repeat the <tt>list</tt> command, this time using just <tt>l</tt>, the next ten lines of the file will be printed out.</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:7) l
@@ -657,11 +644,11 @@ continue edit frame method putl set tmate where</tt></pre>
19 respond_to do |format|
20 format.html # show.html.erb</tt></pre>
</div></div>
<div class="para"><p>And so on until the end of the current file. When the end of file is reached, the <tt>list</tt> command will start again from the beginning of the file and continue again up to the end, treating the file as a circular buffer.</p></div>
<div class="paragraph"><p>And so on until the end of the current file. When the end of file is reached, the <tt>list</tt> command will start again from the beginning of the file and continue again up to the end, treating the file as a circular buffer.</p></div>
<h3 id="_the_context">3.3. The Context</h3>
<div class="para"><p>When you start debugging your application, you will be placed in different contexts as you go through the different parts of the stack.</p></div>
<div class="para"><p>ruby-debug creates a content when a stopping point or an event is reached. The context has information about the suspended program which enables a debugger to inspect the frame stack, evaluate variables from the perspective of the debugged program, and contains information about the place where the debugged program is stopped.</p></div>
<div class="para"><p>At any time you can call the <tt>backtrace</tt> command (or its alias <tt>where</tt>) to print the backtrace of the application. This can be very helpful to know how you got where you are. If you ever wondered about how you got somewhere in your code, then <tt>backtrace</tt> will supply the answer.</p></div>
<div class="paragraph"><p>When you start debugging your application, you will be placed in different contexts as you go through the different parts of the stack.</p></div>
<div class="paragraph"><p>ruby-debug creates a content when a stopping point or an event is reached. The context has information about the suspended program which enables a debugger to inspect the frame stack, evaluate variables from the perspective of the debugged program, and contains information about the place where the debugged program is stopped.</p></div>
<div class="paragraph"><p>At any time you can call the <tt>backtrace</tt> command (or its alias <tt>where</tt>) to print the backtrace of the application. This can be very helpful to know how you got where you are. If you ever wondered about how you got somewhere in your code, then <tt>backtrace</tt> will supply the answer.</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:5) where
@@ -675,18 +662,18 @@ continue edit frame method putl set tmate where</tt></pre>
at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/filters.rb:617
...</tt></pre>
</div></div>
<div class="para"><p>You move anywhere you want in this trace (thus changing the context) by using the <tt>frame <em>n</em></tt> command, where <em>n</em> is the specified frame number.</p></div>
<div class="paragraph"><p>You move anywhere you want in this trace (thus changing the context) by using the <tt>frame <em>n</em></tt> command, where <em>n</em> is the specified frame number.</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:5) frame 2
#2 ActionController::Base.perform_action_without_filters
at line /PathTo/project/vendor/rails/actionpack/lib/action_controller/base.rb:1175</tt></pre>
</div></div>
<div class="para"><p>The available variables are the same as if you were running the code line by line. After all, that's what debugging is.</p></div>
<div class="para"><p>Moving up and down the stack frame: You can use <tt>up [n]</tt> (<tt>u</tt> for abbreviated) and <tt>down [n]</tt> commands in order to change the context <em>n</em> frames up or down the stack respectively. <em>n</em> defaults to one. Up in this case is towards higher-numbered stack frames, and down is towards lower-numbered stack frames.</p></div>
<div class="paragraph"><p>The available variables are the same as if you were running the code line by line. After all, that&#8217;s what debugging is.</p></div>
<div class="paragraph"><p>Moving up and down the stack frame: You can use <tt>up [n]</tt> (<tt>u</tt> for abbreviated) and <tt>down [n]</tt> commands in order to change the context <em>n</em> frames up or down the stack respectively. <em>n</em> defaults to one. Up in this case is towards higher-numbered stack frames, and down is towards lower-numbered stack frames.</p></div>
<h3 id="_threads">3.4. Threads</h3>
<div class="para"><p>The debugger can list, stop, resume and switch between running threads by using the command <tt>thread</tt> (or the abbreviated <tt>th</tt>). This command has a handful of options:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>The debugger can list, stop, resume and switch between running threads by using the command <tt>thread</tt> (or the abbreviated <tt>th</tt>). This command has a handful of options:</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>thread</tt> shows the current thread.
@@ -713,17 +700,17 @@ continue edit frame method putl set tmate where</tt></pre>
</p>
</li>
</ul></div>
<div class="para"><p>This command is very helpful, among other occasions, when you are debugging concurrent threads and need to verify that there are no race conditions in your code.</p></div>
<div class="paragraph"><p>This command is very helpful, among other occasions, when you are debugging concurrent threads and need to verify that there are no race conditions in your code.</p></div>
<h3 id="_inspecting_variables">3.5. Inspecting Variables</h3>
<div class="para"><p>Any expression can be evaluated in the current context. To evaluate an expression, just type it!</p></div>
<div class="para"><p>This example shows how you can print the instance_variables defined within the current context:</p></div>
<div class="paragraph"><p>Any expression can be evaluated in the current context. To evaluate an expression, just type it!</p></div>
<div class="paragraph"><p>This example shows how you can print the instance_variables defined within the current context:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>@posts = Post.find(:all)
(rdb:11) instance_variables
["@_response", "@action_name", "@url", "@_session", "@_cookies", "@performed_render", "@_flash", "@template", "@_params", "@before_filter_chain_aborted", "@request_origin", "@_headers", "@performed_redirect", "@_request"]</tt></pre>
</div></div>
<div class="para"><p>As you may have figured out, all of the variables that you can access from a controller are displayed. This list is dynamically updated as you execute code. For example, run the next line using <tt>next</tt> (you'll learn more about this command later in this guide).</p></div>
<div class="paragraph"><p>As you may have figured out, all of the variables that you can access from a controller are displayed. This list is dynamically updated as you execute code. For example, run the next line using <tt>next</tt> (you&#8217;ll learn more about this command later in this guide).</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:11) next
@@ -733,13 +720,13 @@ Processing PostsController#index (for 127.0.0.1 at 2008-09-04 19:51:34) [GET]
/PathToProject/posts_controller.rb:8
respond_to do |format|</tt></pre>
</div></div>
<div class="para"><p>And then ask again for the instance_variables:</p></div>
<div class="paragraph"><p>And then ask again for the instance_variables:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:11) instance_variables.include? "@posts"
true</tt></pre>
</div></div>
<div class="para"><p>Now <tt>@posts</tt> is a included in the instance variables, because the line defining it was executed.</p></div>
<div class="paragraph"><p>Now <tt>@posts</tt> is a included in the instance variables, because the line defining it was executed.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -748,7 +735,7 @@ true</tt></pre>
<td class="content">You can also step into <strong>irb</strong> mode with the command <tt>irb</tt> (of course!). This way an irb session will be started within the context you invoked it. But be warned: this is an experimental feature.</td>
</tr></table>
</div>
<div class="para"><p>The <tt>var</tt> method is the most convenient way to show variables and their values:</p></div>
<div class="paragraph"><p>The <tt>var</tt> method is the most convenient way to show variables and their values:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>var
@@ -757,13 +744,13 @@ true</tt></pre>
(rdb:1) v[ar] i[nstance] &lt;object&gt; show instance variables of object
(rdb:1) v[ar] l[ocal] show local variables</tt></pre>
</div></div>
<div class="para"><p>This is a great way to inspect the values of the current context variables. For example:</p></div>
<div class="paragraph"><p>This is a great way to inspect the values of the current context variables. For example:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:9) var local
__dbg_verbose_save =&gt; false</tt></pre>
</div></div>
<div class="para"><p>You can also inspect for an object method this way:</p></div>
<div class="paragraph"><p>You can also inspect for an object method this way:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:9) var instance Post.new
@@ -779,16 +766,16 @@ true</tt></pre>
<td class="content">The commands <tt>p</tt> (print) and <tt>pp</tt> (pretty print) can be used to evaluate Ruby expressions and display the value of variables to the console.</td>
</tr></table>
</div>
<div class="para"><p>You can use also <tt>display</tt> to start watching variables. This is a good way of tracking the values of a variable while the execution goes on.</p></div>
<div class="paragraph"><p>You can use also <tt>display</tt> to start watching variables. This is a good way of tracking the values of a variable while the execution goes on.</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:1) display @recent_comments
1: @recent_comments =</tt></pre>
</div></div>
<div class="para"><p>The variables inside the displaying list will be printed with their values after you move in the stack. To stop displaying a variable use <tt>undisplay <em>n</em></tt> where <em>n</em> is the variable number (1 in the last example).</p></div>
<div class="paragraph"><p>The variables inside the displaying list will be printed with their values after you move in the stack. To stop displaying a variable use <tt>undisplay <em>n</em></tt> where <em>n</em> is the variable number (1 in the last example).</p></div>
<h3 id="_step_by_step">3.6. Step by Step</h3>
<div class="para"><p>Now you should know where you are in the running trace and be able to print the available variables. But lets continue and move on with the application execution.</p></div>
<div class="para"><p>Use <tt>step</tt> (abbreviated <tt>s</tt>) to continue running your program until the next logical stopping point and return control to ruby-debug.</p></div>
<div class="paragraph"><p>Now you should know where you are in the running trace and be able to print the available variables. But lets continue and move on with the application execution.</p></div>
<div class="paragraph"><p>Use <tt>step</tt> (abbreviated <tt>s</tt>) to continue running your program until the next logical stopping point and return control to ruby-debug.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -797,9 +784,9 @@ true</tt></pre>
<td class="content">You can also use <tt>step+ <em>n</em></tt> and <tt>step- <em>n</em></tt> to move forward or backward <em>n</em> steps respectively.</td>
</tr></table>
</div>
<div class="para"><p>You may also use <tt>next</tt> which is similar to step, but function or method calls that appear within the line of code are executed without stopping. As with step, you may use plus sign to move <em>n</em> steps.</p></div>
<div class="para"><p>The difference between <tt>next</tt> and <tt>step</tt> is that <tt>step</tt> stops at the next line of code executed, doing just a single step, while <tt>next</tt> moves to the next line without descending inside methods.</p></div>
<div class="para"><p>For example, consider this block of code with an included <tt>debugger</tt> statement:</p></div>
<div class="paragraph"><p>You may also use <tt>next</tt> which is similar to step, but function or method calls that appear within the line of code are executed without stopping. As with step, you may use plus sign to move <em>n</em> steps.</p></div>
<div class="paragraph"><p>The difference between <tt>next</tt> and <tt>step</tt> is that <tt>step</tt> stops at the next line of code executed, doing just a single step, while <tt>next</tt> moves to the next line without descending inside methods.</p></div>
<div class="paragraph"><p>For example, consider this block of code with an included <tt>debugger</tt> statement:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -817,8 +804,7 @@ http://www.gnu.org/software/src-highlite -->
<span style="color: #990000">:</span>limit <span style="color: #990000">=&gt;</span> limit
<span style="color: #990000">)</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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -839,7 +825,7 @@ Loading development environment (Rails 2.1.0)
/PathTo/project/app/models/author.rb:11
)</tt></pre>
</div></div>
<div class="para"><p>With the code stopped, take a look around:</p></div>
<div class="paragraph"><p>With the code stopped, take a look around:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:1) list
@@ -853,14 +839,14 @@ Loading development environment (Rails 2.1.0)
12 end
13 end</tt></pre>
</div></div>
<div class="para"><p>You are at the end of the line, but&#8230; was this line executed? You can inspect the instance variables.</p></div>
<div class="paragraph"><p>You are at the end of the line, but... was this line executed? You can inspect the instance variables.</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:1) var instance
@attributes = {"updated_at"=&gt;"2008-07-31 12:46:10", "id"=&gt;"1", "first_name"=&gt;"Bob", "las...
@attributes_cache = {}</tt></pre>
</div></div>
<div class="para"><p><tt>@recent_comments</tt> hasn't been defined yet, so it's clear that this line hasn't been executed yet. Use the <tt>next</tt> command to move on in the code:</p></div>
<div class="paragraph"><p><tt>@recent_comments</tt> hasn&#8217;t been defined yet, so it&#8217;s clear that this line hasn&#8217;t been executed yet. Use the <tt>next</tt> command to move on in the code:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:1) next
@@ -872,12 +858,12 @@ Loading development environment (Rails 2.1.0)
@comments = []
@recent_comments = []</tt></pre>
</div></div>
<div class="para"><p>Now you can see that the <tt>@comments</tt> relationship was loaded and @recent_comments defined because the line was executed.</p></div>
<div class="para"><p>If you want to go deeper into the stack trace you can move single <tt>steps</tt>, through your calling methods and into Rails code. This is one of the best ways to find bugs in your code, or perhaps in Ruby or Rails.</p></div>
<div class="paragraph"><p>Now you can see that the <tt>@comments</tt> relationship was loaded and @recent_comments defined because the line was executed.</p></div>
<div class="paragraph"><p>If you want to go deeper into the stack trace you can move single <tt>steps</tt>, through your calling methods and into Rails code. This is one of the best ways to find bugs in your code, or perhaps in Ruby or Rails.</p></div>
<h3 id="_breakpoints">3.7. Breakpoints</h3>
<div class="para"><p>A breakpoint makes your application stop whenever a certain point in the program is reached. The debugger shell is invoked in that line.</p></div>
<div class="para"><p>You can add breakpoints dynamically with the command <tt>break</tt> (or just <tt>b</tt>). There are 3 possible ways of adding breakpoints manually:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>A breakpoint makes your application stop whenever a certain point in the program is reached. The debugger shell is invoked in that line.</p></div>
<div class="paragraph"><p>You can add breakpoints dynamically with the command <tt>break</tt> (or just <tt>b</tt>). There are 3 possible ways of adding breakpoints manually:</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>break line</tt>: set breakpoint in the <em>line</em> in the current source file.
@@ -890,7 +876,7 @@ Loading development environment (Rails 2.1.0)
</li>
<li>
<p>
<tt>break class(.|#)method [if expression]</tt>: set breakpoint in <em>method</em> (. and # for class and instance method respectively) defined in <em>class</em>. The <em>expression</em> works the same way as with file:line.
<tt>break class(.|#)method [if expression]</tt>: set breakpoint in <em>method</em> (. and \# for class and instance method respectively) defined in <em>class</em>. The <em>expression</em> works the same way as with file:line.
</p>
</li>
</ul></div>
@@ -899,22 +885,22 @@ Loading development environment (Rails 2.1.0)
<pre><tt>(rdb:5) break 10
Breakpoint 1 file /PathTo/project/vendor/rails/actionpack/lib/action_controller/filters.rb, line 10</tt></pre>
</div></div>
<div class="para"><p>Use <tt>info breakpoints <em>n</em></tt> or <tt>info break <em>n</em></tt> to list breakpoints. If you supply a number, it lists that breakpoint. Otherwise it lists all breakpoints.</p></div>
<div class="paragraph"><p>Use <tt>info breakpoints <em>n</em></tt> or <tt>info break <em>n</em></tt> to list breakpoints. If you supply a number, it lists that breakpoint. Otherwise it lists all breakpoints.</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:5) info breakpoints
Num Enb What
1 y at filters.rb:10</tt></pre>
</div></div>
<div class="para"><p>To delete breakpoints: use the command <tt>delete <em>n</em></tt> to remove the breakpoint number <em>n</em>. If no number is specified, it deletes all breakpoints that are currently active..</p></div>
<div class="paragraph"><p>To delete breakpoints: use the command <tt>delete <em>n</em></tt> to remove the breakpoint number <em>n</em>. If no number is specified, it deletes all breakpoints that are currently active..</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>(rdb:5) delete 1
(rdb:5) info breakpoints
No breakpoints.</tt></pre>
</div></div>
<div class="para"><p>You can also enable or disable breakpoints:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>You can also enable or disable breakpoints:</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>enable breakpoints</tt>: allow a list <em>breakpoints</em> or all of them if no list is specified, to stop your program. This is the default state when you create a breakpoint.
@@ -927,11 +913,11 @@ No breakpoints.</tt></pre>
</li>
</ul></div>
<h3 id="_catching_exceptions">3.8. Catching Exceptions</h3>
<div class="para"><p>The command <tt>catch exception-name</tt> (or just <tt>cat exception-name</tt>) can be used to intercept an exception of type <em>exception-name</em> when there would otherwise be is no handler for it.</p></div>
<div class="para"><p>To list all active catchpoints use <tt>catch</tt>.</p></div>
<div class="paragraph"><p>The command <tt>catch exception-name</tt> (or just <tt>cat exception-name</tt>) can be used to intercept an exception of type <em>exception-name</em> when there would otherwise be is no handler for it.</p></div>
<div class="paragraph"><p>To list all active catchpoints use <tt>catch</tt>.</p></div>
<h3 id="_resuming_execution">3.9. Resuming Execution</h3>
<div class="para"><p>There are two ways to resume execution of an application that is stopped in the debugger:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>There are two ways to resume execution of an application that is stopped in the debugger:</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>continue</tt> [line-specification] (or <tt>c</tt>): resume program execution, at the address where your script last stopped; any breakpoints set at that address are bypassed. The optional argument line-specification allows you to specify a line number to set a one-time breakpoint which is deleted when that breakpoint is reached.
@@ -944,8 +930,8 @@ No breakpoints.</tt></pre>
</li>
</ul></div>
<h3 id="_editing">3.10. Editing</h3>
<div class="para"><p>Two commands allow you to open code from the debugger into an editor:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>Two commands allow you to open code from the debugger into an editor:</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>edit [file:line]</tt>: edit <em>file</em> using the editor specified by the EDITOR environment variable. A specific <em>line</em> can also be given.
@@ -958,11 +944,11 @@ No breakpoints.</tt></pre>
</li>
</ul></div>
<h3 id="_quitting">3.11. Quitting</h3>
<div class="para"><p>To exit the debugger, use the <tt>quit</tt> command (abbreviated <tt>q</tt>), or its alias <tt>exit</tt>.</p></div>
<div class="para"><p>A simple quit tries to terminate all threads in effect. Therefore your server will be stopped and you will have to start it again.</p></div>
<div class="paragraph"><p>To exit the debugger, use the <tt>quit</tt> command (abbreviated <tt>q</tt>), or its alias <tt>exit</tt>.</p></div>
<div class="paragraph"><p>A simple quit tries to terminate all threads in effect. Therefore your server will be stopped and you will have to start it again.</p></div>
<h3 id="_settings">3.12. Settings</h3>
<div class="para"><p>There are some settings that can be configured in ruby-debug to make it easier to debug your code. Here are a few of the available options:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>There are some settings that can be configured in ruby-debug to make it easier to debug your code. Here are a few of the available options:</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>set reload</tt>: Reload source code when changed.
@@ -984,7 +970,7 @@ No breakpoints.</tt></pre>
</p>
</li>
</ul></div>
<div class="para"><p>You can see the full list by using <tt>help set</tt>. Use <tt>help set <em>subcommand</em></tt> to learn about a particular <tt>set</tt> command.</p></div>
<div class="paragraph"><p>You can see the full list by using <tt>help set</tt>. Use <tt>help set <em>subcommand</em></tt> to learn about a particular <tt>set</tt> command.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -993,7 +979,7 @@ No breakpoints.</tt></pre>
<td class="content">You can include any number of these configuration lines inside a <tt>.rdebugrc</tt> file in your HOME directory. ruby-debug will read this file every time it is loaded. and configure itself accordingly.</td>
</tr></table>
</div>
<div class="para"><p>Here's a good start for an <tt>.rdebugrc</tt>:</p></div>
<div class="paragraph"><p>Here&#8217;s a good start for an <tt>.rdebugrc</tt>:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>set autolist
@@ -1003,37 +989,36 @@ set listsize 25</tt></pre>
</div>
<h2 id="_debugging_memory_leaks">4. Debugging Memory Leaks</h2>
<div class="sectionbody">
<div class="para"><p>A Ruby application (on Rails or not), can leak memory - either in the Ruby code or at the C code level.</p></div>
<div class="para"><p>In this section, you will learn how to find and fix such leaks by using Bleak House and Valgrind debugging tools.</p></div>
<div class="paragraph"><p>A Ruby application (on Rails or not), can leak memory - either in the Ruby code or at the C code level.</p></div>
<div class="paragraph"><p>In this section, you will learn how to find and fix such leaks by using Bleak House and Valgrind debugging tools.</p></div>
<h3 id="_bleakhouse">4.1. BleakHouse</h3>
<div class="para"><p><a href="http://github.com/fauna/bleak_house/tree/master">BleakHouse</a> is a library for finding memory leaks.</p></div>
<div class="para"><p>If a Ruby object does not go out of scope, the Ruby Garbage Collector won't sweep it since it is referenced somewhere. Leaks like this can grow slowly and your application will consume more and more memory, gradually affecting the overall system performance. This tool will help you find leaks on the Ruby heap.</p></div>
<div class="para"><p>To install it run:</p></div>
<div class="paragraph"><p><a href="http://github.com/fauna/bleak_house/tree/master">BleakHouse</a> is a library for finding memory leaks.</p></div>
<div class="paragraph"><p>If a Ruby object does not go out of scope, the Ruby Garbage Collector won&#8217;t sweep it since it is referenced somewhere. Leaks like this can grow slowly and your application will consume more and more memory, gradually affecting the overall system performance. This tool will help you find leaks on the Ruby heap.</p></div>
<div class="paragraph"><p>To install it run:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>sudo gem install bleak_house</tt></pre>
</div></div>
<div class="para"><p>Then setup you application for profiling. Then add the following at the bottom of config/environment.rb:</p></div>
<div class="paragraph"><p>Then setup you application for profiling. Then add the following at the bottom of config/environment.rb:</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: #000080">require</span></span> <span style="color: #FF0000">'bleak_house'</span> <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> ENV<span style="color: #990000">[</span><span style="color: #FF0000">'BLEAK_HOUSE'</span><span style="color: #990000">]</span>
</tt></pre></div></div>
<div class="para"><p>Start a server instance with BleakHouse integration:</p></div>
<pre><tt><span style="font-weight: bold"><span style="color: #000080">require</span></span> <span style="color: #FF0000">'bleak_house'</span> <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> ENV<span style="color: #990000">[</span><span style="color: #FF0000">'BLEAK_HOUSE'</span><span style="color: #990000">]</span></tt></pre></div></div>
<div class="paragraph"><p>Start a server instance with BleakHouse integration:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>RAILS_ENV=production BLEAK_HOUSE=1 ruby-bleak-house ./script/server</tt></pre>
</div></div>
<div class="para"><p>Make sure to run a couple hundred requests to get better data samples, then press <tt>CTRL-C</tt>. The server will stop and Bleak House will produce a dumpfile in <tt>/tmp</tt>:</p></div>
<div class="paragraph"><p>Make sure to run a couple hundred requests to get better data samples, then press <tt>CTRL-C</tt>. The server will stop and Bleak House will produce a dumpfile in <tt>/tmp</tt>:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>** BleakHouse: working...
** BleakHouse: complete
** Bleakhouse: run 'bleak /tmp/bleak.5979.0.dump' to analyze.</tt></pre>
</div></div>
<div class="para"><p>To analyze it, just run the listed command. The top 20 leakiest lines will be listed:</p></div>
<div class="paragraph"><p>To analyze it, just run the listed command. The top 20 leakiest lines will be listed:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt> 191691 total objects
@@ -1049,17 +1034,17 @@ http://www.gnu.org/software/src-highlite -->
834 /opt/local//lib/ruby/site_ruby/1.8/rubygems/version.rb:146:Array
...</tt></pre>
</div></div>
<div class="para"><p>This way you can find where your application is leaking memory and fix it.</p></div>
<div class="para"><p>If <a href="http://github.com/fauna/bleak_house/tree/master">BleakHouse</a> doesn't report any heap growth but you still have memory growth, you might have a broken C extension, or real leak in the interpreter. In that case, try using Valgrind to investigate further.</p></div>
<div class="paragraph"><p>This way you can find where your application is leaking memory and fix it.</p></div>
<div class="paragraph"><p>If <a href="http://github.com/fauna/bleak_house/tree/master">BleakHouse</a> doesn&#8217;t report any heap growth but you still have memory growth, you might have a broken C extension, or real leak in the interpreter. In that case, try using Valgrind to investigate further.</p></div>
<h3 id="_valgrind">4.2. Valgrind</h3>
<div class="para"><p><a href="http://valgrind.org/">Valgrind</a> is a Linux-only application for detecting C-based memory leaks and race conditions.</p></div>
<div class="para"><p>There are Valgrind tools that can automatically detect many memory management and threading bugs, and profile your programs in detail. For example, a C extension in the interpreter calls <tt>malloc()</tt> but is doesn't properly call <tt>free()</tt>, this memory won't be available until the app terminates.</p></div>
<div class="para"><p>For further information on how to install Valgrind and use with Ruby, refer to <a href="http://blog.evanweaver.com/articles/2008/02/05/valgrind-and-ruby/">Valgrind and Ruby</a> by Evan Weaver.</p></div>
<div class="paragraph"><p><a href="http://valgrind.org/">Valgrind</a> is a Linux-only application for detecting C-based memory leaks and race conditions.</p></div>
<div class="paragraph"><p>There are Valgrind tools that can automatically detect many memory management and threading bugs, and profile your programs in detail. For example, a C extension in the interpreter calls <tt>malloc()</tt> but is doesn&#8217;t properly call <tt>free()</tt>, this memory won&#8217;t be available until the app terminates.</p></div>
<div class="paragraph"><p>For further information on how to install Valgrind and use with Ruby, refer to <a href="http://blog.evanweaver.com/articles/2008/02/05/valgrind-and-ruby/">Valgrind and Ruby</a> by Evan Weaver.</p></div>
</div>
<h2 id="_plugins_for_debugging">5. Plugins for Debugging</h2>
<div class="sectionbody">
<div class="para"><p>There are some Rails plugins to help you to find errors and debug your application. Here is a list of useful plugins for debugging:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>There are some Rails plugins to help you to find errors and debug your application. Here is a list of useful plugins for debugging:</p></div>
<div class="ulist"><ul>
<li>
<p>
<a href="http://github.com/drnic/rails-footnotes/tree/master">Footnotes</a>: Every Rails page has footnotes that give request information and link back to your source via TextMate.
@@ -1094,7 +1079,7 @@ http://www.gnu.org/software/src-highlite -->
</div>
<h2 id="_references">6. References</h2>
<div class="sectionbody">
<div class="ilist"><ul>
<div class="ulist"><ul>
<li>
<p>
<a href="http://www.datanoise.com/ruby-debug">ruby-debug Homepage</a>
@@ -1112,17 +1097,17 @@ http://www.gnu.org/software/src-highlite -->
</li>
<li>
<p>
<a href="http://railscasts.com/episodes/54-debugging-with-ruby-debug">Ryan Bate's ruby-debug screencast</a>
<a href="http://railscasts.com/episodes/54-debugging-with-ruby-debug">Ryan Bate&#8217;s ruby-debug screencast</a>
</p>
</li>
<li>
<p>
<a href="http://railscasts.com/episodes/24-the-stack-trace">Ryan Bate's stack trace screencast</a>
<a href="http://railscasts.com/episodes/24-the-stack-trace">Ryan Bate&#8217;s stack trace screencast</a>
</p>
</li>
<li>
<p>
<a href="http://railscasts.com/episodes/56-the-logger">Ryan Bate's logger screencast</a>
<a href="http://railscasts.com/episodes/56-the-logger">Ryan Bate&#8217;s logger screencast</a>
</p>
</li>
<li>
@@ -1149,8 +1134,8 @@ http://www.gnu.org/software/src-highlite -->
</div>
<h2 id="_changelog">7. Changelog</h2>
<div class="sectionbody">
<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/5">Lighthouse ticket</a></p></div>
<div class="ilist"><ul>
<div class="paragraph"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/5">Lighthouse ticket</a></p></div>
<div class="ulist"><ul>
<li>
<p>
November 3, 2008: Accepted for publication. Added RJS, memory leaks and plugins chapters by <a href="../authors.html#miloops">Emilio Tagua</a>

View File

@@ -217,6 +217,8 @@ ul#navMain {
<li><a href="#_placeholder_conditions">Placeholder Conditions</a></li>
<li><a href="#_hash_conditions">Hash Conditions</a></li>
</ul>
</li>
<li>
@@ -232,6 +234,9 @@ ul#navMain {
<a href="#_group">Group</a>
</li>
<li>
<a href="#_having">Having</a>
</li>
<li>
<a href="#_read_only">Read Only</a>
</li>
<li>
@@ -305,8 +310,8 @@ ul#navMain {
<h1>Rails Finders</h1>
<div id="preamble">
<div class="sectionbody">
<div class="para"><p>This guide covers the <tt>find</tt> method defined in <tt>ActiveRecord::Base</tt>, as well as other ways of finding particular instances of your models. By using this guide, you will be able to:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>This guide covers the <tt>find</tt> method defined in ActiveRecord::Base, as well as other ways of finding particular instances of your models. By using this guide, you will be able to:</p></div>
<div class="ulist"><ul>
<li>
<p>
Find records using a variety of methods and conditions
@@ -343,13 +348,13 @@ Perform aggregate calculations on Active Record models
</p>
</li>
</ul></div>
<div class="para"><p>If you're used to using raw SQL to find database records, you'll find that there are generally better ways to carry out the same operations in Rails. Active Record insulates you from the need to use SQL in most cases.</p></div>
<div class="para"><p>The SQL in your log may have some quoting, and that quoting depends on the backend (MySQL, for example, puts backticks around field and table names). Attempting to copy the raw SQL contained within this guide may not work in your database system. Please consult the database systems manual before attempting to execute any SQL.</p></div>
<div class="paragraph"><p>If you&#8217;re used to using raw SQL to find database records, you&#8217;ll find that there are generally better ways to carry out the same operations in Rails. Active Record insulates you from the need to use SQL in most cases.</p></div>
<div class="paragraph"><p>The SQL in your log may have some quoting, and that quoting depends on the backend (MySQL, for example, puts backticks around field and table names). Attempting to copy the raw SQL contained within this guide may not work in your database system. Please consult the database systems manual before attempting to execute any SQL.</p></div>
</div>
</div>
<h2 id="_the_sample_models">1. The Sample Models</h2>
<div class="sectionbody">
<div class="para"><p>This guide demonstrates finding using the following models:</p></div>
<div class="paragraph"><p>This guide demonstrates finding using the following models:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -375,23 +380,21 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Role <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
has_and_belongs_to_many <span style="color: #990000">:</span>clients
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
</div>
<h2 id="_database_agnostic">2. Database Agnostic</h2>
<div class="sectionbody">
<div class="para"><p>Active Record will perform queries on the database for you and is compatible with most database systems (MySQL, PostgreSQL and SQLite to name a few). Regardless of which database system you're using, the Active Record method format will always be the same.</p></div>
<div class="paragraph"><p>Active Record will perform queries on the database for you and is compatible with most database systems (MySQL, PostgreSQL and SQLite to name a few). Regardless of which database system you&#8217;re using, the Active Record method format will always be the same.</p></div>
</div>
<h2 id="_ids_first_last_and_all">3. IDs, First, Last and All</h2>
<div class="sectionbody">
<div class="para"><p><tt>ActiveRecord::Base</tt> has methods defined on it to make interacting with your database and the tables within it much, much easier. For finding records, the key method is <tt>find</tt>. This method allows you to pass arguments into it to perform certain queries on your database without the need of SQL. If you wanted to find the record with the id of 1, you could type <tt>Client.find(1)</tt> which would execute this query on your database:</p></div>
<div class="paragraph"><p>ActiveRecord::Base has methods defined on it to make interacting with your database and the tables within it much, much easier. For finding records, the key method is <tt>find</tt>. This method allows you to pass arguments into it to perform certain queries on your database without the need of SQL. If you wanted to find the record with the id of 1, you could type <tt>Client.find(1)</tt> which would execute this query on your database:</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">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>clients<span style="color: #990000">.</span>id <span style="color: #990000">=</span> <span style="color: #993399">1</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>clients<span style="color: #990000">.</span>id <span style="color: #990000">=</span> <span style="color: #993399">1</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -400,14 +403,13 @@ http://www.gnu.org/software/src-highlite -->
<td class="content">Because this is a standard table created from a migration in Rails, the primary key is defaulted to <em>id</em>. If you have specified a different primary key in your migrations, this is what Rails will find on when you call the find method, not the id column.</td>
</tr></table>
</div>
<div class="para"><p>If you wanted to find clients with id 1 or 2, you call <tt>Client.find([1,2])</tt> or <tt>Client.find(1,2)</tt> and then this will be executed as:</p></div>
<div class="paragraph"><p>If you wanted to find clients with id 1 or 2, you call <tt>Client.find([1,2])</tt> or <tt>Client.find(1,2)</tt> and then this will be executed as:</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">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>clients<span style="color: #990000">.</span>id <span style="font-weight: bold"><span style="color: #0000FF">IN</span></span> <span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">,</span><span style="color: #993399">2</span><span style="color: #990000">))</span>
</tt></pre></div></div>
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>clients<span style="color: #990000">.</span>id <span style="font-weight: bold"><span style="color: #0000FF">IN</span></span> <span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">,</span><span style="color: #993399">2</span><span style="color: #990000">))</span></tt></pre></div></div>
<div class="listingblock">
<div class="content">
<pre><tt>&gt;&gt; Client.find(1,2)
@@ -416,46 +418,44 @@ http://www.gnu.org/software/src-highlite -->
#&lt;Client id: 2, name: =&gt; "Michael", locked: false, orders_count: 3,
created_at: "2008-09-28 13:12:40", updated_at: "2008-09-28 13:12:40"&gt;]</tt></pre>
</div></div>
<div class="para"><p>Note that if you pass in a list of numbers that the result will be returned as an array, not as a single <tt>Client</tt> object.</p></div>
<div class="paragraph"><p>Note that if you pass in a list of numbers that the result will be returned as an array, not as a single Client object.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
<td class="content">If <tt>find(id)</tt> or <tt>find([id1, id2])</tt> fails to find any records, it will raise a <tt>RecordNotFound</tt> exception.</td>
<td class="content">If <tt>find(id)</tt> or <tt>find([id1, id2])</tt> fails to find any records, it will raise a RecordNotFound exception.</td>
</tr></table>
</div>
<div class="para"><p>If you wanted to find the first Client object you would simply type <tt>Client.first</tt> and that would find the first client in your clients table:</p></div>
<div class="paragraph"><p>If you wanted to find the first Client object you would simply type <tt>Client.first</tt> and that would find the first client in your clients table:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&gt;&gt; Client.first
=&gt; #&lt;Client id: 1, name: =&gt; "Ryan", locked: false, orders_count: 2,
created_at: "2008-09-28 15:38:50", updated_at: "2008-09-28 15:38:50"&gt;</tt></pre>
</div></div>
<div class="para"><p>If you were reading your log file (the default is log/development.log) you may see something like this:</p></div>
<div class="paragraph"><p>If you were reading your log file (the default is log/development.log) you may see something like this:</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">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">1</span>
</tt></pre></div></div>
<div class="para"><p>Indicating the query that Rails has performed on your database.</p></div>
<div class="para"><p>To find the last Client object you would simply type <tt>Client.last</tt> and that would find the last client created in your clients table:</p></div>
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">1</span></tt></pre></div></div>
<div class="paragraph"><p>Indicating the query that Rails has performed on your database.</p></div>
<div class="paragraph"><p>To find the last Client object you would simply type <tt>Client.last</tt> and that would find the last client created in your clients table:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&gt;&gt; Client.last
=&gt; #&lt;Client id: 2, name: =&gt; "Michael", locked: false, orders_count: 3,
created_at: "2008-09-28 13:12:40", updated_at: "2008-09-28 13:12:40"&gt;</tt></pre>
</div></div>
<div class="para"><p>If you were reading your log file (the default is log/development.log) you may see something like this:</p></div>
<div class="paragraph"><p>If you were reading your log file (the default is log/development.log) you may see something like this:</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">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">ORDER</span></span> <span style="font-weight: bold"><span style="color: #0000FF">BY</span></span> id <span style="font-weight: bold"><span style="color: #0000FF">DESC</span></span> <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">1</span>
</tt></pre></div></div>
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">ORDER</span></span> <span style="font-weight: bold"><span style="color: #0000FF">BY</span></span> id <span style="font-weight: bold"><span style="color: #0000FF">DESC</span></span> <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">1</span></tt></pre></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -469,9 +469,8 @@ http://www.gnu.org/software/src-highlite -->
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">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">ORDER</span></span> <span style="font-weight: bold"><span style="color: #0000FF">BY</span></span> clients<span style="color: #990000">.</span>id <span style="font-weight: bold"><span style="color: #0000FF">DESC</span></span> <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">1</span>
</tt></pre></div></div>
<div class="para"><p>To find all the Client objects you would simply type <tt>Client.all</tt> and that would find all the clients in your clients table:</p></div>
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">ORDER</span></span> <span style="font-weight: bold"><span style="color: #0000FF">BY</span></span> clients<span style="color: #990000">.</span>id <span style="font-weight: bold"><span style="color: #0000FF">DESC</span></span> <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">1</span></tt></pre></div></div>
<div class="paragraph"><p>To find all the Client objects you would simply type <tt>Client.all</tt> and that would find all the clients in your clients table:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&gt;&gt; Client.all
@@ -480,41 +479,39 @@ http://www.gnu.org/software/src-highlite -->
#&lt;Client id: 2, name: =&gt; "Michael", locked: false, orders_count: 3,
created_at: "2008-09-28 13:12:40", updated_at: "2008-09-28 13:12:40"&gt;]</tt></pre>
</div></div>
<div class="para"><p>You may see in Rails code that there are calls to methods such as <tt>Client.find(:all)</tt>, <tt>Client.find(:first)</tt> and <tt>Client.find(:last)</tt>. These methods are just alternatives to <tt>Client.all</tt>, <tt>Client.first</tt> and <tt>Client.last</tt> respectively.</p></div>
<div class="para"><p>Be aware that <tt>Client.first</tt>/<tt>Client.find(:first)</tt> and <tt>Client.last</tt>/<tt>Client.find(:last)</tt> will both return a single object, where as <tt>Client.all</tt>/<tt>Client.find(:all)</tt> will return an array of Client objects, just as passing in an array of ids to <tt>find</tt> will do also.</p></div>
<div class="paragraph"><p>You may see in Rails code that there are calls to methods such as <tt>Client.find(:all)</tt>, <tt>Client.find(:first)</tt> and <tt>Client.find(:last)</tt>. These methods are just alternatives to <tt>Client.all</tt>, <tt>Client.first</tt> and <tt>Client.last</tt> respectively.</p></div>
<div class="paragraph"><p>Be aware that <tt>Client.first</tt>/<tt>Client.find(:first)</tt> and <tt>Client.last</tt>/<tt>Client.find(:last)</tt> will both return a single object, where as <tt>Client.all</tt>/<tt>Client.find(:all)</tt> will return an array of Client objects, just as passing in an array of ids to <tt>find</tt> will do also.</p></div>
</div>
<h2 id="_conditions">4. Conditions</h2>
<div class="sectionbody">
<div class="para"><p>The <tt>find</tt> method allows you to specify conditions to limit the records returned. You can specify conditions as a string, array, or hash.</p></div>
<div class="paragraph"><p>The <tt>find</tt> method allows you to specify conditions to limit the records returned. You can specify conditions as a string, array, or hash.</p></div>
<h3 id="_pure_string_conditions">4.1. Pure String Conditions</h3>
<div class="para"><p>If you'd like to add conditions to your find, you could just specify them in there, just like <tt>Client.first(:conditions &#8658; "orders_count = <em>2</em>")</tt>. This will find all clients where the <tt>orders_count</tt> field's value is 2.</p></div>
<div class="paragraph"><p>If you&#8217;d like to add conditions to your find, you could just specify them in there, just like <tt>Client.first(:conditions =&gt; "orders_count = <em>2</em>")</tt>. This will find all clients where the <tt>orders_count</tt> field&#8217;s value is 2.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/warning.png" alt="Warning" />
</td>
<td class="content">Building your own conditions as pure strings can leave you vulnerable to SQL injection exploits. For example, <tt>Client.first(:conditions &#8658; "name LIKE <em>%#{params[:name]}%</em>")</tt> is not safe. See the next section for the preferred way to handle conditions using an array.</td>
<td class="content">Building your own conditions as pure strings can leave you vulnerable to SQL injection exploits. For example, <tt>Client.first(:conditions =&gt; "name LIKE <em>%#{params[:name]}%</em>")</tt> is not safe. See the next section for the preferred way to handle conditions using an array.</td>
</tr></table>
</div>
<h3 id="_array_conditions">4.2. Array Conditions</h3>
<div class="para"><p>Now what if that number could vary, say as a parameter from somewhere, or perhaps from the user's level status somewhere? The find then becomes something like <tt>Client.first(:conditions &#8658; ["orders_count = ?", params[:orders]])</tt>. Active Record will go through the first element in the conditions value and any additional elements will replace the question marks (?) in the first element. If you want to specify two conditions, you can do it like <tt>Client.first(:conditions &#8658; ["orders_count = ? AND locked = ?", params[:orders], false])</tt>. In this example, the first question mark will be replaced with the value in <tt>params[:orders]</tt> and the second will be replaced with <tt>false</tt> and this will find the first record in the table that has <em>2</em> as its value for the <tt>orders_count</tt> field and <tt>false</tt> for its locked field.</p></div>
<div class="para"><p>The reason for doing code like:</p></div>
<div class="paragraph"><p>Now what if that number could vary, say as a argument from somewhere, or perhaps from the user&#8217;s level status somewhere? The find then becomes something like <tt>Client.first(:conditions =&gt; ["orders_count = ?", params[:orders]])</tt>. Active Record will go through the first element in the conditions value and any additional elements will replace the question marks (?) in the first element. If you want to specify two conditions, you can do it like <tt>Client.first(:conditions =&gt; ["orders_count = ? AND locked = ?", params[:orders], false])</tt>. In this example, the first question mark will be replaced with the value in <tt>params[:orders]</tt> and the second will be replaced with the SQL representation of <tt>false</tt>, which depends on the adapter.</p></div>
<div class="paragraph"><p>The reason for doing code like:</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>Client<span style="color: #990000">.</span>first<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">"orders_count = ?"</span><span style="color: #990000">,</span> params<span style="color: #990000">[:</span>orders<span style="color: #990000">]])</span>
</tt></pre></div></div>
<div class="para"><p>instead of:</p></div>
<pre><tt>Client<span style="color: #990000">.</span>first<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">"orders_count = ?"</span><span style="color: #990000">,</span> params<span style="color: #990000">[:</span>orders<span style="color: #990000">]])</span></tt></pre></div></div>
<div class="paragraph"><p>instead of:</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>Client<span style="color: #990000">.</span>first<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"orders_count = #{params[:orders]}"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>is because of parameter safety. Putting the variable directly into the conditions string will pass the variable to the database <strong>as-is</strong>. This means that it will be an unescaped variable directly from a user who may have malicious intent. If you do this, you put your entire database at risk because once a user finds out he or she can exploit your database they can do just about anything to it. Never ever put your parameters directly inside the conditions string.</p></div>
<pre><tt>Client<span style="color: #990000">.</span>first<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"orders_count = #{params[:orders]}"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>is because of argument safety. Putting the variable directly into the conditions string will pass the variable to the database <strong>as-is</strong>. This means that it will be an unescaped variable directly from a user who may have malicious intent. If you do this, you put your entire database at risk because once a user finds out he or she can exploit your database they can do just about anything to it. Never ever put your arguments directly inside the conditions string.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -523,16 +520,15 @@ http://www.gnu.org/software/src-highlite -->
<td class="content">For more information on the dangers of SQL injection, see the <a href="../security.html#_sql_injection">Ruby on Rails Security Guide</a>.</td>
</tr></table>
</div>
<div class="para"><p>If you're looking for a range inside of a table (for example, users created in a certain timeframe) you can use the conditions option coupled with the IN sql statement for this. If you had two dates coming in from a controller you could do something like this to look for a range:</p></div>
<div class="paragraph"><p>If you&#8217;re looking for a range inside of a table (for example, users created in a certain timeframe) you can use the conditions option coupled with the IN sql statement for this. If you had two dates coming in from a controller you could do something like this to look for a range:</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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at IN (?)"</span><span style="color: #990000">,</span>
<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>start_date<span style="color: #990000">].</span>to_date<span style="color: #990000">)..(</span>params<span style="color: #990000">[:</span>end_date<span style="color: #990000">].</span>to_date<span style="color: #990000">)])</span>
</tt></pre></div></div>
<div class="para"><p>This would generate the proper query which is great for small ranges but not so good for larger ranges. For example if you pass in a range of date objects spanning a year that's 365 (or possibly 366, depending on the year) strings it will attempt to match your field against.</p></div>
<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>start_date<span style="color: #990000">].</span>to_date<span style="color: #990000">)..(</span>params<span style="color: #990000">[:</span>end_date<span style="color: #990000">].</span>to_date<span style="color: #990000">)])</span></tt></pre></div></div>
<div class="paragraph"><p>This would generate the proper query which is great for small ranges but not so good for larger ranges. For example if you pass in a range of date objects spanning a year that&#8217;s 365 (or possibly 366, depending on the year) strings it will attempt to match your field against.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -545,17 +541,15 @@ http://www.gnu.org/software/src-highlite -->
<span style="color: #FF0000">'2008-01-18'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-19'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-20'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-21'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-22'</span><span style="color: #990000">,</span><span style="color: #FF0000">'2008-01-23'</span><span style="color: #990000">,...</span>
<span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">15</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">16</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">17</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">18</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">19</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">20</span><span style="color: #FF0000">',</span>
<span style="color: #FF0000"> '</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">21</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">22</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">23</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">24</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">25</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">26</span><span style="color: #FF0000">',</span>
<span style="color: #FF0000"> '</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">27</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">28</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">29</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">30</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">31</span><span style="color: #FF0000">'))</span>
</tt></pre></div></div>
<div class="para"><p>Things can get <strong>really</strong> messy if you pass in time objects as it will attempt to compare your field to <strong>every second</strong> in that range:</p></div>
<span style="color: #FF0000"> '</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">27</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">28</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">29</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">30</span><span style="color: #FF0000">','</span><span style="color: #993399">2008</span><span style="color: #990000">-</span><span style="color: #993399">12</span><span style="color: #990000">-</span><span style="color: #993399">31</span><span style="color: #FF0000">'))</span></tt></pre></div></div>
<div class="paragraph"><p>Things can get <strong>really</strong> messy if you pass in Time objects as it will attempt to compare your field to <strong>every second</strong> in that range:</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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at IN (?)"</span><span style="color: #990000">,</span>
<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>start_date<span style="color: #990000">].</span>to_date<span style="color: #990000">.</span>to_time<span style="color: #990000">)..(</span>params<span style="color: #990000">[:</span>end_date<span style="color: #990000">].</span>to_date<span style="color: #990000">.</span>to_time<span style="color: #990000">)])</span>
</tt></pre></div></div>
<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>start_date<span style="color: #990000">].</span>to_date<span style="color: #990000">.</span>to_time<span style="color: #990000">)..(</span>params<span style="color: #990000">[:</span>end_date<span style="color: #990000">].</span>to_date<span style="color: #990000">.</span>to_time<span style="color: #990000">)])</span></tt></pre></div></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -563,119 +557,185 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> users <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>created_at <span style="font-weight: bold"><span style="color: #0000FF">IN</span></span>
<span style="color: #990000">(</span><span style="color: #FF0000">'2007-12-01 00:00:00'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'2007-12-01 00:00:01'</span> <span style="color: #990000">...</span>
<span style="color: #FF0000">'2007-12-01 23:59:59'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'2007-12-02 00:00:00'</span><span style="color: #990000">))</span>
</tt></pre></div></div>
<div class="para"><p>This could possibly cause your database server to raise an unexpected error, for example MySQL will throw back this error:</p></div>
<span style="color: #FF0000">'2007-12-01 23:59:59'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'2007-12-02 00:00:00'</span><span style="color: #990000">))</span></tt></pre></div></div>
<div class="paragraph"><p>This could possibly cause your database server to raise an unexpected error, for example MySQL will throw back this error:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>Got a packet bigger than 'max_allowed_packet' bytes: _query_</tt></pre>
</div></div>
<div class="para"><p>Where <em>query</em> is the actual query used to get that error.</p></div>
<div class="para"><p>In this example it would be better to use greater-than and less-than operators in SQL, like so:</p></div>
<div class="paragraph"><p>Where <em>query</em> is the actual query used to get that error.</p></div>
<div class="paragraph"><p>In this example it would be better to use greater-than and less-than operators in SQL, like so:</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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span>
<span style="color: #990000">[</span><span style="color: #FF0000">"created_at &gt; ? AND created_at &lt; ?"</span><span style="color: #990000">,</span> params<span style="color: #990000">[:</span>start_date<span style="color: #990000">],</span> params<span style="color: #990000">[:</span>end_date<span style="color: #990000">]])</span>
</tt></pre></div></div>
<div class="para"><p>You can also use the greater-than-or-equal-to and less-than-or-equal-to like this:</p></div>
<span style="color: #990000">[</span><span style="color: #FF0000">"created_at &gt; ? AND created_at &lt; ?"</span><span style="color: #990000">,</span> params<span style="color: #990000">[:</span>start_date<span style="color: #990000">],</span> params<span style="color: #990000">[:</span>end_date<span style="color: #990000">]])</span></tt></pre></div></div>
<div class="paragraph"><p>You can also use the greater-than-or-equal-to and less-than-or-equal-to like this:</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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span>
<span style="color: #990000">[</span><span style="color: #FF0000">"created_at &gt;= ? AND created_at &lt;= ?"</span><span style="color: #990000">,</span> params<span style="color: #990000">[:</span>start_date<span style="color: #990000">],</span> params<span style="color: #990000">[:</span>end_date<span style="color: #990000">]])</span>
</tt></pre></div></div>
<div class="para"><p>Just like in Ruby.</p></div>
<span style="color: #990000">[</span><span style="color: #FF0000">"created_at &gt;= ? AND created_at &lt;= ?"</span><span style="color: #990000">,</span> params<span style="color: #990000">[:</span>start_date<span style="color: #990000">],</span> params<span style="color: #990000">[:</span>end_date<span style="color: #990000">]])</span></tt></pre></div></div>
<div class="paragraph"><p>Just like in Ruby. If you want a shorter syntax be sure to check out the <a href="#_hash_conditions">Hash Conditions</a> section later on in the guide.</p></div>
<h3 id="_placeholder_conditions">4.3. Placeholder Conditions</h3>
<div class="para"><p>Similar to the array style of params you can also specify keys in your conditions:</p></div>
<div class="paragraph"><p>Similar to the array style of params you can also specify keys in your conditions:</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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span>
<span style="color: #990000">[</span><span style="color: #FF0000">"created_at &gt;= :start_date AND created_at &lt;= :end_date"</span><span style="color: #990000">,</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>start_date <span style="color: #990000">=&gt;</span> params<span style="color: #990000">[:</span>start_date<span style="color: #990000">],</span> <span style="color: #990000">:</span>end_date <span style="color: #990000">=&gt;</span> params<span style="color: #990000">[:</span>end_date<span style="color: #990000">]</span> <span style="color: #FF0000">}</span><span style="color: #990000">])</span>
</tt></pre></div></div>
<div class="para"><p>This makes for clearer readability if you have a large number of variable conditions.</p></div>
<span style="color: #990000">[</span><span style="color: #FF0000">"created_at &gt;= :start_date AND created_at &lt;= :end_date"</span><span style="color: #990000">,</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>start_date <span style="color: #990000">=&gt;</span> params<span style="color: #990000">[:</span>start_date<span style="color: #990000">],</span> <span style="color: #990000">:</span>end_date <span style="color: #990000">=&gt;</span> params<span style="color: #990000">[:</span>end_date<span style="color: #990000">]</span> <span style="color: #FF0000">}</span><span style="color: #990000">])</span></tt></pre></div></div>
<div class="paragraph"><p>This makes for clearer readability if you have a large number of variable conditions.</p></div>
<h3 id="_hash_conditions">4.4. Hash Conditions</h3>
<div class="paragraph"><p>Rails also allows you to pass in a hash conditions which can increase the readability of your conditions syntax. With hash conditions, you pass in a hash with keys of the fields you want conditionalised and the values of how you want to conditionalise them:</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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>locked <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span> <span style="color: #FF0000">}</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>The field name does not have to be a symbol it can also be a string:</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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #FF0000">'locked'</span> <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span> <span style="color: #FF0000">}</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>The good thing about this is that we can pass in a range for our fields without it generating a large query as shown in the preamble of this section.</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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>created_at <span style="color: #990000">=&gt;</span> <span style="color: #990000">(</span>Time<span style="color: #990000">.</span>now<span style="color: #990000">.</span>midnight <span style="color: #990000">-</span> <span style="color: #993399">1</span><span style="color: #990000">.</span>day<span style="color: #990000">)..</span>Time<span style="color: #990000">.</span>now<span style="color: #990000">.</span>midnight<span style="color: #FF0000">}</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>This will find all clients created yesterday by using a BETWEEN sql statement:</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">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> <span style="color: #FF0000">`clients`</span> <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span><span style="color: #FF0000">`clients`</span><span style="color: #990000">.</span><span style="color: #FF0000">`created_at`</span> <span style="font-weight: bold"><span style="color: #0000FF">BETWEEN</span></span> <span style="color: #FF0000">'2008-12-21 00:00:00'</span> <span style="font-weight: bold"><span style="color: #0000FF">AND</span></span> <span style="color: #FF0000">'2008-12-22 00:00:00'</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>This demonstrates a shorter syntax for the examples in <a href="#_array_conditions">Array Conditions</a></p></div>
<div class="paragraph"><p>You can also join in tables and specify their columns in the hash:</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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"orders"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #FF0000">'orders.created_at'</span> <span style="color: #990000">=&gt;</span> <span style="color: #990000">(</span>Time<span style="color: #990000">.</span>now<span style="color: #990000">.</span>midnight <span style="color: #990000">-</span> <span style="color: #993399">1</span><span style="color: #990000">.</span>day<span style="color: #990000">)..</span>Time<span style="color: #990000">.</span>now<span style="color: #990000">.</span>midnight <span style="color: #FF0000">}</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>An alternative and cleaner syntax to this is:</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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"orders"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>orders <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>created_at <span style="color: #990000">=&gt;</span> <span style="color: #990000">(</span>Time<span style="color: #990000">.</span>now<span style="color: #990000">.</span>midnight <span style="color: #990000">-</span> <span style="color: #993399">1</span><span style="color: #990000">.</span>day<span style="color: #990000">)..</span>Time<span style="color: #990000">.</span>now<span style="color: #990000">.</span>midnight <span style="color: #FF0000">}</span> <span style="color: #FF0000">}</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>This will find all clients who have orders that were created yesterday, again using a BETWEEN expression.</p></div>
<div class="paragraph"><p>If you want to find records using the IN expression you can pass an array to the conditions hash:</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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"orders"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>orders_count <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #993399">1</span><span style="color: #990000">,</span><span style="color: #993399">3</span><span style="color: #990000">,</span><span style="color: #993399">5</span><span style="color: #990000">]</span> <span style="color: #FF0000">}</span></tt></pre></div></div>
<div class="paragraph"><p>This code will generate SQL like this:</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">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> <span style="color: #FF0000">`clients`</span> <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span><span style="color: #FF0000">`clients`</span><span style="color: #990000">.</span><span style="color: #FF0000">`orders_count`</span> <span style="font-weight: bold"><span style="color: #0000FF">IN</span></span> <span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">,</span><span style="color: #993399">2</span><span style="color: #990000">,</span><span style="color: #993399">3</span><span style="color: #990000">))</span></tt></pre></div></div>
</div>
<h2 id="_ordering">5. Ordering</h2>
<div class="sectionbody">
<div class="para"><p>If you're getting a set of records and want to force an order, you can use <tt>Client.all(:order &#8658; "created_at")</tt> which by default will sort the records by ascending order. If you'd like to order it in descending order, just tell it to do that using <tt>Client.all(:order &#8658; "created_at desc")</tt></p></div>
<div class="paragraph"><p>If you&#8217;re getting a set of records and want to order them in ascending order by the <tt>created_at</tt> field in your table, you can use <tt>Client.all(:order =&gt; "created_at")</tt>. If you&#8217;d like to order it in descending order, just tell it to do that using <tt>Client.all(:order =&gt; "created_at desc")</tt>. The value for this option is passed in as sanitized SQL and allows you to sort via multiple fields: <tt>Client.all(:order =&gt; "created_at desc, orders_count asc")</tt>.</p></div>
</div>
<h2 id="_selecting_certain_fields">6. Selecting Certain Fields</h2>
<div class="sectionbody">
<div class="para"><p>To select certain fields, you can use the select option like this: <tt>Client.first(:select &#8658; "viewable_by, locked")</tt>. This select option does not use an array of fields, but rather requires you to type SQL-like code. The above code will execute <tt>SELECT viewable_by, locked FROM clients LIMIT 0,1</tt> on your database.</p></div>
<div class="para"><p>You can also call SQL functions within the select option. For example, if you would like to only grab a single record per unique value in a certain field by using the <tt>DISTINCT</tt> function you can do it like this: <tt>Client.all(:select &#8658; "DISTINCT(name)")</tt>.</p></div>
<div class="paragraph"><p>To select certain fields, you can use the select option like this: <tt>Client.first(:select =&gt; "viewable_by, locked")</tt>. This select option does not use an array of fields, but rather requires you to type SQL-like code. The above code will execute <tt>SELECT viewable_by, locked FROM clients LIMIT 1</tt> on your database.</p></div>
<div class="paragraph"><p>Be careful because this also means you&#8217;re initializing a model object with only the fields that you&#8217;ve selected. If you attempt to access a field that is not in the initialized record you&#8217;ll receive:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>ActiveRecord::MissingAttributeError: missing attribute: &lt;attribute&gt;</tt></pre>
</div></div>
<div class="paragraph"><p>Where &lt;attribute&gt; is the atrribute you asked for. The <tt>id</tt> method will not raise the <tt>ActiveRecord::MissingAttributeError</tt>, so just be careful when working with associations because they need the <tt>id</tt> method to function properly.</p></div>
<div class="paragraph"><p>You can also call SQL functions within the select option. For example, if you would like to only grab a single record per unique value in a certain field by using the <tt>DISTINCT</tt> function you can do it like this: <tt>Client.all(:select =&gt; "DISTINCT(name)")</tt>.</p></div>
</div>
<h2 id="_limit_amp_offset">7. Limit &amp; Offset</h2>
<div class="sectionbody">
<div class="para"><p>If you want to limit the amount of records to a certain subset of all the records retrieved you usually use limit for this, sometimes coupled with offset. Limit is the maximum number of records that will be retrieved from a query, and offset is the number of records it will start reading from from the first record of the set. Take this code for example:</p></div>
<div class="paragraph"><p>If you want to limit the amount of records to a certain subset of all the records retrieved you usually use limit for this, sometimes coupled with offset. Limit is the maximum number of records that will be retrieved from a query, and offset is the number of records it will start reading from from the first record of the set. Take this code for example:</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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>limit <span style="color: #990000">=&gt;</span> <span style="color: #993399">5</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>This code will return a maximum of 5 clients and because it specifies no offset it will return the first 5 clients in the table. The SQL it executes will look like this:</p></div>
<pre><tt>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>limit <span style="color: #990000">=&gt;</span> <span style="color: #993399">5</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>This code will return a maximum of 5 clients and because it specifies no offset it will return the first 5 clients in the table. The SQL it executes will look like this:</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">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">5</span>
</tt></pre></div></div>
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">5</span></tt></pre></div></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>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>limit <span style="color: #990000">=&gt;</span> <span style="color: #993399">5</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>offset <span style="color: #990000">=&gt;</span> <span style="color: #993399">5</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>This code will return a maximum of 5 clients and because it specifies an offset this time, it will return these records starting from the 5th client in the clients table. The SQL looks like:</p></div>
<pre><tt>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>limit <span style="color: #990000">=&gt;</span> <span style="color: #993399">5</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>offset <span style="color: #990000">=&gt;</span> <span style="color: #993399">5</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>This code will return a maximum of 5 clients and because it specifies an offset this time, it will return these records starting from the 5th client in the clients table. The SQL looks like:</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">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">5</span><span style="color: #990000">,</span> <span style="color: #993399">5</span>
</tt></pre></div></div>
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">5</span><span style="color: #990000">,</span> <span style="color: #993399">5</span></tt></pre></div></div>
</div>
<h2 id="_group">8. Group</h2>
<div class="sectionbody">
<div class="para"><p>The group option for find is useful, for example, if you want to find a collection of the dates orders were created on. You could use the option in this context:</p></div>
<div class="paragraph"><p>The group option for find is useful, for example, if you want to find a collection of the dates orders were created on. You could use the option in this context:</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>Order<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>group <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"date(created_at)"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>order <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"created_at"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>And this will give you a single <tt>Order</tt> object for each date where there are orders in the database.</p></div>
<div class="para"><p>The SQL that would be executed would be something like this:</p></div>
<pre><tt>Order<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>group <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"date(created_at)"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>order <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"created_at"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>And this will give you a single <tt>Order</tt> object for each date where there are orders in the database.</p></div>
<div class="paragraph"><p>The SQL that would be executed would be something like this:</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">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> orders <span style="font-weight: bold"><span style="color: #0000FF">GROUP</span></span> <span style="font-weight: bold"><span style="color: #0000FF">BY</span></span> <span style="color: #009900">date</span><span style="color: #990000">(</span>created_at<span style="color: #990000">)</span>
</tt></pre></div></div>
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> orders <span style="font-weight: bold"><span style="color: #0000FF">GROUP</span></span> <span style="font-weight: bold"><span style="color: #0000FF">BY</span></span> <span style="color: #009900">date</span><span style="color: #990000">(</span>created_at<span style="color: #990000">)</span></tt></pre></div></div>
</div>
<h2 id="_read_only">9. Read Only</h2>
<h2 id="_having">9. Having</h2>
<div class="sectionbody">
<div class="para"><p>Readonly is a find option that you can set in order to make that instance of the record read-only. Any attempt to alter or destroy the record will not succeed, raising an <tt>Active Record::ReadOnlyRecord</tt> exception. To set this option, specify it like this:</p></div>
<div class="paragraph"><p>The <tt>:having</tt> option allows you to specify SQL and acts as a kind of a filter on the group option. <tt>:having</tt> can only be specified when <tt>:group</tt> is specified.</p></div>
<div class="paragraph"><p>An example of using it would be:</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>Client<span style="color: #990000">.</span>first<span style="color: #990000">(:</span>readonly <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>If you assign this record to a variable <tt>client</tt>, calling the following code will raise an <tt>ActiveRecord::ReadOnlyRecord</tt> exception:</p></div>
<pre><tt>Order<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>group <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"date(created_at)"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>having <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at &gt; ?"</span><span style="color: #990000">,</span> <span style="color: #993399">1</span><span style="color: #990000">.</span>month<span style="color: #990000">.</span>ago<span style="color: #990000">])</span></tt></pre></div></div>
<div class="paragraph"><p>This will return single order objects for each day, but only for the last month.</p></div>
</div>
<h2 id="_read_only">10. Read Only</h2>
<div class="sectionbody">
<div class="paragraph"><p><tt>readonly</tt> is a <tt>find</tt> option that you can set in order to make that instance of the record read-only. Any attempt to alter or destroy the record will not succeed, raising an ActiveRecord::ReadOnlyRecord exception. To set this option, specify it like this:</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>Client<span style="color: #990000">.</span>first<span style="color: #990000">(:</span>readonly <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>If you assign this record to a variable client, calling the following code will raise an ActiveRecord::ReadOnlyRecord exception:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -683,12 +743,11 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>client <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>first<span style="color: #990000">(:</span>readonly <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">)</span>
client<span style="color: #990000">.</span>locked <span style="color: #990000">=</span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
client<span style="color: #990000">.</span>save
</tt></pre></div></div>
client<span style="color: #990000">.</span>save</tt></pre></div></div>
</div>
<h2 id="_lock">10. Lock</h2>
<h2 id="_lock">11. Lock</h2>
<div class="sectionbody">
<div class="para"><p>If you're wanting to stop race conditions for a specific record (for example, you're incrementing a single field for a record, potentially from multiple simultaneous connections) you can use the lock option to ensure that the record is updated correctly. For safety, you should use this inside a transaction.</p></div>
<div class="paragraph"><p>If you&#8217;re wanting to stop race conditions for a specific record (for example, you&#8217;re incrementing a single field for a record, potentially from multiple simultaneous connections) you can use the lock option to ensure that the record is updated correctly. For safety, you should use this inside a transaction.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -697,16 +756,25 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt>Topic<span style="color: #990000">.</span>transaction <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
t <span style="color: #990000">=</span> Topic<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">],</span> <span style="color: #990000">:</span>lock <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">)</span>
t<span style="color: #990000">.</span>increment!<span style="color: #990000">(:</span>views<span style="color: #990000">)</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>You can also pass SQL to this option to allow different types of locks. For example, MySQL has an expression called LOCK IN SHARE MODE where you can lock a record but still allow other queries to read it. To specify this expression just pass it in as the lock option:</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>Topic<span style="color: #990000">.</span>transaction <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
t <span style="color: #990000">=</span> Topic<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">],</span> <span style="color: #990000">:</span>lock <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"LOCK IN SHARE MODE"</span><span style="color: #990000">)</span>
t<span style="color: #990000">.</span>increment!<span style="color: #990000">(:</span>views<span style="color: #990000">)</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
</div>
<h2 id="_making_it_all_work_together">11. Making It All Work Together</h2>
<h2 id="_making_it_all_work_together">12. Making It All Work Together</h2>
<div class="sectionbody">
<div class="para"><p>You can chain these options together in no particular order as Active Record will write the correct SQL for you. If you specify two instances of the same options inside the find statement Active Record will use the latter.</p></div>
<div class="paragraph"><p>You can chain these options together in no particular order as Active Record will write the correct SQL for you. If you specify two instances of the same options inside the <tt>find</tt> method Active Record will use the last one you specified. This is because the options passed to find are a hash and defining the same key twice in a hash will result in the last definition being used.</p></div>
</div>
<h2 id="_eager_loading">12. Eager Loading</h2>
<h2 id="_eager_loading">13. Eager Loading</h2>
<div class="sectionbody">
<div class="para"><p>Eager loading is loading associated records along with any number of records in as few queries as possible. For example, if you wanted to load all the addresses associated with all the clients in a single query you could use <tt>Client.all(:include &#8658; :address)</tt>. If you wanted to include both the address and mailing address for the client you would use +Client.find(:all, :include &#8658; [:address, :mailing_address]). Include will first find the client records and then load the associated address records. Running script/server in one window, and executing the code through script/console in another window, the output should look similar to this:</p></div>
<div class="paragraph"><p>Eager loading is loading associated records along with any number of records in as few queries as possible. For example, if you wanted to load all the addresses associated with all the clients in a single query you could use <tt>Client.all(:include =&gt; :address)</tt>. If you wanted to include both the address and mailing address for the client you would use <tt>Client.find(:all, :include =&gt; [:address, :mailing_address])</tt>. Include will first find the client records and then load the associated address records. Running script/server in one window, and executing the code through script/console in another window, the output should look similar to this:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -716,10 +784,10 @@ http://www.gnu.org/software/src-highlite -->
Address <span style="font-weight: bold"><span style="color: #0000FF">Load</span></span> <span style="color: #990000">(</span><span style="color: #993399">0.119770</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> addresses<span style="color: #990000">.*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> addresses
<span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>addresses<span style="color: #990000">.</span>client_id <span style="font-weight: bold"><span style="color: #0000FF">IN</span></span> <span style="color: #990000">(</span><span style="color: #993399">13</span><span style="color: #990000">,</span><span style="color: #993399">14</span><span style="color: #990000">))</span>
MailingAddress <span style="font-weight: bold"><span style="color: #0000FF">Load</span></span> <span style="color: #990000">(</span><span style="color: #993399">0.001985</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> mailing_addresses<span style="color: #990000">.*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span>
mailing_addresses <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>mailing_addresses<span style="color: #990000">.</span>client_id <span style="font-weight: bold"><span style="color: #0000FF">IN</span></span> <span style="color: #990000">(</span><span style="color: #993399">13</span><span style="color: #990000">,</span><span style="color: #993399">14</span><span style="color: #990000">))</span>
</tt></pre></div></div>
<div class="para"><p>The numbers <tt>13</tt> and <tt>14</tt> in the above SQL are the ids of the clients gathered from the <tt>Client.all</tt> query. Rails will then run a query to gather all the addresses and mailing addresses that have a client_id of 13 or 14. Although this is done in 3 queries, this is more efficient than not eager loading because without eager loading it would run a query for every time you called <tt>address</tt> or <tt>mailing_address</tt> on one of the objects in the clients array, which may lead to performance issues if you're loading a large number of records at once.</p></div>
<div class="para"><p>If you wanted to get all the addresses for a client in the same query you would do <tt>Client.all(:joins &#8658; :address)</tt> and you wanted to find the address and mailing address for that client you would do <tt>Client.all(:joins &#8658; [:address, :mailing_address])</tt>. This is more efficient because it does all the SQL in one query, as shown by this example:</p></div>
mailing_addresses <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>mailing_addresses<span style="color: #990000">.</span>client_id <span style="font-weight: bold"><span style="color: #0000FF">IN</span></span> <span style="color: #990000">(</span><span style="color: #993399">13</span><span style="color: #990000">,</span><span style="color: #993399">14</span><span style="color: #990000">))</span></tt></pre></div></div>
<div class="paragraph"><p>The numbers <tt>13</tt> and <tt>14</tt> in the above SQL are the ids of the clients gathered from the <tt>Client.all</tt> query. Rails will then run a query to gather all the addresses and mailing addresses that have a client_id of 13 or 14. Although this is done in 3 queries, this is more efficient than not eager loading because without eager loading it would run a query for every time you called <tt>address</tt> or <tt>mailing_address</tt> on one of the objects in the clients array, which may lead to performance issues if you&#8217;re loading a large number of records at once and is often called the "N+1 query problem". The problem is that the more queries your server has to execute, the slower it will run.</p></div>
<div class="paragraph"><p>If you wanted to get all the addresses for a client in the same query you would do <tt>Client.all(:joins =&gt; :address)</tt>.
If you wanted to find the address and mailing address for that client you would do <tt>Client.all(:joins =&gt; [:address, :mailing_address])</tt>. This is more efficient because it does all the SQL in one query, as shown by this example:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -727,9 +795,8 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="color: #990000">+</span>Client <span style="font-weight: bold"><span style="color: #0000FF">Load</span></span> <span style="color: #990000">(</span><span style="color: #993399">0.000455</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> clients<span style="color: #990000">.*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">INNER</span></span> <span style="font-weight: bold"><span style="color: #0000FF">JOIN</span></span> addresses
<span style="font-weight: bold"><span style="color: #0000FF">ON</span></span> addresses<span style="color: #990000">.</span>client_id <span style="color: #990000">=</span> client<span style="color: #990000">.</span>id <span style="font-weight: bold"><span style="color: #0000FF">INNER</span></span> <span style="font-weight: bold"><span style="color: #0000FF">JOIN</span></span> mailing_addresses <span style="font-weight: bold"><span style="color: #0000FF">ON</span></span>
mailing_addresses<span style="color: #990000">.</span>client_id <span style="color: #990000">=</span> client<span style="color: #990000">.</span>id
</tt></pre></div></div>
<div class="para"><p>This query is more efficent, but there's a gotcha: if you have a client who does not have an address or a mailing address they will not be returned in this query at all. If you have any association as an optional association, you may want to use include rather than joins. Alternatively, you can use a SQL join clause to specify exactly the join you need (Rails always assumes an inner join):</p></div>
mailing_addresses<span style="color: #990000">.</span>client_id <span style="color: #990000">=</span> client<span style="color: #990000">.</span>id</tt></pre></div></div>
<div class="paragraph"><p>This query is more efficent, but there&#8217;s a gotcha: if you have a client who does not have an address or a mailing address they will not be returned in this query at all. If you have any association as an optional association, you may want to use include rather than joins. Alternatively, you can use a SQL join clause to specify exactly the join you need (Rails always assumes an inner join):</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -737,25 +804,23 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>Client<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>joins <span style="color: #990000">=&gt;</span> “LEFT OUTER JOIN addresses ON
client<span style="color: #990000">.</span>id <span style="color: #990000">=</span> addresses<span style="color: #990000">.</span>client_id LEFT OUTER JOIN mailing_addresses ON
client<span style="color: #990000">.</span>id <span style="color: #990000">=</span> mailing_addresses<span style="color: #990000">.</span>client_id”<span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>When using eager loading you can specify conditions for the columns of the tables inside the eager loading to get back a smaller subset. If, for example, you want to find a client and all their orders within the last two weeks you could use eager loading with conditions for this:</p></div>
client<span style="color: #990000">.</span>id <span style="color: #990000">=</span> mailing_addresses<span style="color: #990000">.</span>client_id”<span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>When using eager loading you can specify conditions for the columns of the tables inside the eager loading to get back a smaller subset. If, for example, you want to find a client and all their orders within the last two weeks you could use eager loading with conditions for this:</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>Client<span style="color: #990000">.</span>first<span style="color: #990000">(:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"orders"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span>
<span style="color: #990000">[</span><span style="color: #FF0000">"orders.created_at &gt;= ? AND orders.created_at &lt;= ?"</span><span style="color: #990000">,</span> Time<span style="color: #990000">.</span>now <span style="color: #990000">-</span> <span style="color: #993399">2</span><span style="color: #990000">.</span>weeks<span style="color: #990000">,</span> Time<span style="color: #990000">.</span>now<span style="color: #990000">])</span>
</tt></pre></div></div>
<span style="color: #990000">[</span><span style="color: #FF0000">"orders.created_at &gt;= ? AND orders.created_at &lt;= ?"</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">.</span>weeks<span style="color: #990000">.</span>ago<span style="color: #990000">,</span> Time<span style="color: #990000">.</span>now<span style="color: #990000">])</span></tt></pre></div></div>
</div>
<h2 id="_dynamic_finders">13. Dynamic finders</h2>
<h2 id="_dynamic_finders">14. Dynamic finders</h2>
<div class="sectionbody">
<div class="para"><p>For every field (also known as an attribute) you define in your table, Active Record provides a finder method. If you have a field called <tt>name</tt> on your Client model for example, you get <tt>find_by_name</tt> and <tt>find_all_by_name</tt> for free from Active Record. If you have also have a <tt>locked</tt> field on the client model, you also get <tt>find_by_locked</tt> and <tt>find_all_by_locked</tt>.</p></div>
<div class="para"><p>You can do <tt>find_last_by_*</tt> methods too which will find the last record matching your parameter.</p></div>
<div class="para"><p>You can specify an exclamation point (!) on the end of the dynamic finders to get them to raise an <tt>ActiveRecord::RecordNotFound</tt> error if they do not return any records, like <tt>Client.find_by_name!(<em>Ryan</em>)</tt></p></div>
<div class="para"><p>If you want to find both by name and locked, you can chain these finders together by simply typing <tt>and</tt> between the fields for example <tt>Client.find_by_name_and_locked(<em>Ryan</em>, true)</tt>.</p></div>
<div class="para"><p>There's another set of dynamic finders that let you find or create/initialize objects if they aren't find. These work in a similar fashion to the other finders and can be used like <tt>find_or_create_by_name(params[:name])</tt>. Using this will firstly perform a find and then create if the find returns nil. The SQL looks like this for <tt>Client.find_or_create_by_name(<em>Ryan</em>)</tt>:</p></div>
<div class="paragraph"><p>For every field (also known as an attribute) you define in your table, Active Record provides a finder method. If you have a field called <tt>name</tt> on your Client model for example, you get <tt>find_by_name</tt> and <tt>find_all_by_name</tt> for free from Active Record. If you have also have a <tt>locked</tt> field on the Client model, you also get <tt>find_by_locked</tt> and <tt>find_all_by_locked</tt>.</p></div>
<div class="paragraph"><p>You can do <tt>find_last_by_*</tt> methods too which will find the last record matching your argument.</p></div>
<div class="paragraph"><p>You can specify an exclamation point (!) on the end of the dynamic finders to get them to raise an ActiveRecord::RecordNotFound error if they do not return any records, like <tt>Client.find_by_name!("Ryan")</tt></p></div>
<div class="paragraph"><p>If you want to find both by name and locked, you can chain these finders together by simply typing <tt>and</tt> between the fields for example <tt>Client.find_by_name_and_locked("Ryan", true)</tt>.</p></div>
<div class="paragraph"><p>There&#8217;s another set of dynamic finders that let you find or create/initialize objects if they aren&#8217;t found. These work in a similar fashion to the other finders and can be used like <tt>find_or_create_by_name(params[:name])</tt>. Using this will firstly perform a find and then create if the find returns nil. The SQL looks like this for <tt>Client.find_or_create_by_name("Ryan")</tt>:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -764,51 +829,47 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> <span style="color: #990000">*</span> <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>clients<span style="color: #990000">.</span>name <span style="color: #990000">=</span> <span style="color: #FF0000">'Ryan'</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">LIMIT</span></span> <span style="color: #993399">1</span>
BEGIN
<span style="font-weight: bold"><span style="color: #0000FF">INSERT</span></span> <span style="font-weight: bold"><span style="color: #0000FF">INTO</span></span> clients <span style="color: #990000">(</span>name<span style="color: #990000">,</span> updated_at<span style="color: #990000">,</span> created_at<span style="color: #990000">,</span> orders_count<span style="color: #990000">,</span> locked<span style="color: #990000">)</span>
<span style="font-weight: bold"><span style="color: #0000FF">VALUES</span></span><span style="color: #990000">(</span><span style="color: #FF0000">'Ryan'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'2008-09-28 15:39:12'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'2008-09-28 15:39:12'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'0'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'0'</span><span style="color: #990000">)</span>
COMMIT
</tt></pre></div></div>
<div class="para"><p><tt>find_or_create</tt>'s sibling, <tt>find_or_initialize</tt>, will find an object and if it does not exist will act similar to calling <tt>new</tt> with the parameters you passed in. For example:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">VALUES</span></span><span style="color: #990000">(</span><span style="color: #FF0000">'Ryan'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'2008-09-28 15:39:12'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'2008-09-28 15:39:12'</span><span style="color: #990000">,</span> <span style="color: #993399">0</span><span style="color: #990000">,</span> <span style="color: #FF0000">'0'</span><span style="color: #990000">)</span>
COMMIT</tt></pre></div></div>
<div class="paragraph"><p><tt>find_or_create</tt>'s sibling, <tt>find_or_initialize</tt>, will find an object and if it does not exist will act similar to calling <tt>new</tt> with the arguments you passed in. For example:</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>client <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>find_or_initialize_by_name<span style="color: #990000">(</span><span style="color: #FF0000">'Ryan'</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>will either assign an existing client object with the name <em>Ryan</em> to the client local variable, or initialize new object similar to calling <tt>Client.new(:name &#8658; <em>Ryan</em>)</tt>. From here, you can modify other fields in client by calling the attribute setters on it: <tt>client.locked = true</tt> and when you want to write it to the database just call <tt>save</tt> on it.</p></div>
<pre><tt>client <span style="color: #990000">=</span> Client<span style="color: #990000">.</span>find_or_initialize_by_name<span style="color: #990000">(</span><span style="color: #FF0000">'Ryan'</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>will either assign an existing client object with the name <em>Ryan</em> to the client local variable, or initialize a new object similar to calling <tt>Client.new(:name =&gt; <em>Ryan</em>)</tt>. From here, you can modify other fields in client by calling the attribute setters on it: <tt>client.locked = true</tt> and when you want to write it to the database just call <tt>save</tt> on it.</p></div>
</div>
<h2 id="_finding_by_sql">14. Finding By SQL</h2>
<h2 id="_finding_by_sql">15. Finding By SQL</h2>
<div class="sectionbody">
<div class="para"><p>If you'd like to use your own SQL to find records a table you can use <tt>find_by_sql</tt>. The <tt>find_by_sql</tt> method will return an array of objects even if it only returns a single record in it's call to the database. For example you could run this query:</p></div>
<div class="paragraph"><p>If you&#8217;d like to use your own SQL to find records in a table you can use <tt>find_by_sql</tt>. The <tt>find_by_sql</tt> method will return an array of objects even the underlying query returns just a single record. For example you could run this query:</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>Client<span style="color: #990000">.</span>find_by_sql<span style="color: #990000">(</span><span style="color: #FF0000">"SELECT * FROM clients INNER JOIN orders ON clients.id = orders.client_id ORDER clients.created_at desc"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p><tt>find_by_sql</tt> provides you with a simple way of making custom calls to the database and retrieving instantiated objects.</p></div>
<pre><tt>Client<span style="color: #990000">.</span>find_by_sql<span style="color: #990000">(</span><span style="color: #FF0000">"SELECT * FROM clients INNER JOIN orders ON clients.id = orders.client_id ORDER clients.created_at desc"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p><tt>find_by_sql</tt> provides you with a simple way of making custom calls to the database and retrieving instantiated objects.</p></div>
</div>
<h2 id="_tt_select_all_tt">15. <tt>select_all</tt></h2>
<h2 id="_tt_select_all_tt">16. <tt>select_all</tt></h2>
<div class="sectionbody">
<div class="para"><p><tt>find_by_sql</tt> has a close relative called <tt>connection#select_all</tt>. <tt>select_all</tt> will retrieve objects from the database using custom SQL just like <tt>find_by_sql</tt> but will not instantiate them. Instead, you will get an array of hashes where each hash indicates a record.</p></div>
<div class="paragraph"><p><tt>find_by_sql</tt> has a close relative called <tt>connection#select_all</tt>. <tt>select_all</tt> will retrieve objects from the database using custom SQL just like <tt>find_by_sql</tt> but will not instantiate them. Instead, you will get an array of hashes where each hash indicates a record.</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>Client<span style="color: #990000">.</span>connection<span style="color: #990000">.</span>select_all<span style="color: #990000">(</span><span style="color: #FF0000">"SELECT * FROM `clients` WHERE `id` = '1'"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<pre><tt>Client<span style="color: #990000">.</span>connection<span style="color: #990000">.</span>select_all<span style="color: #990000">(</span><span style="color: #FF0000">"SELECT * FROM `clients` WHERE `id` = '1'"</span><span style="color: #990000">)</span></tt></pre></div></div>
</div>
<h2 id="_working_with_associations">16. Working with Associations</h2>
<h2 id="_working_with_associations">17. Working with Associations</h2>
<div class="sectionbody">
<div class="para"><p>When you define a has_many association on a model you get the find method and dynamic finders also on that association. This is helpful for finding associated records within the scope of an existing record, for example finding all the orders for a client that have been sent and not received by doing something like <tt>Client.find(params[:id]).orders.find_by_sent_and_received(true, false)</tt>. Having this find method available on associations is extremely helpful when using nested controllers.</p></div>
<div class="paragraph"><p>When you define a has_many association on a model you get the <tt>find</tt> method and dynamic finders also on that association. This is helpful for finding associated records within the scope of an existing record, for example finding all the orders for a client that have been sent and not received by doing something like <tt>Client.find(params[:id]).orders.find_by_sent_and_received(true, false)</tt>. Having this find method available on associations is extremely helpful when using nested resources.</p></div>
</div>
<h2 id="_named_scopes">17. Named Scopes</h2>
<h2 id="_named_scopes">18. Named Scopes</h2>
<div class="sectionbody">
<div class="para"><p>Named scopes are another way to add custom finding behavior to the models in the application. Named scopes provide an object-oriented way to narrow the results of a query.</p></div>
<h3 id="_simple_named_scopes">17.1. Simple Named Scopes</h3>
<div class="para"><p>Suppose want to find all clients who are male. You could use this code:</p></div>
<div class="paragraph"><p>Named scopes are another way to add custom finding behavior to the models in the application. Named scopes provide an object-oriented way to narrow the results of a query.</p></div>
<h3 id="_simple_named_scopes">18.1. Simple Named Scopes</h3>
<div class="paragraph"><p>Suppose we want to find all clients who are male. You could use this code:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -816,10 +877,9 @@ 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> Client <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
named_scope <span style="color: #990000">:</span>males<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>gender <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"male"</span> <span style="color: #FF0000">}</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>Then you could call <tt>Client.males.all</tt> to get all the clients who are male. Please note that if you do not specify the <tt>all</tt> on the end you will get a <tt>Scope</tt> object back, not a set of records which you do get back if you put the <tt>all</tt> on the end.</p></div>
<div class="para"><p>If you wanted to find all the clients who are active, you could use this:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Then you could call <tt>Client.males.all</tt> to get all the clients who are male. Please note that if you do not specify the <tt>all</tt> on the end you will get a <tt>Scope</tt> object back, not a set of records which you do get back if you put the <tt>all</tt> on the end.</p></div>
<div class="paragraph"><p>If you wanted to find all the clients who are active, you could use this:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -827,28 +887,25 @@ 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> Client <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
named_scope <span style="color: #990000">:</span>active<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>active <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span> <span style="color: #FF0000">}</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>You can call this new named_scope with <tt>Client.active.all</tt> and this will do the same query as if we just used <tt>Client.all(:conditions &#8658; ["active = ?", true])</tt>. Please be aware that the conditions syntax in named_scope and find is different and the two are not interchangeable. If you want to find the first client within this named scope you could do <tt>Client.active.first</tt>.</p></div>
<h3 id="_combining_named_scopes">17.2. Combining Named Scopes</h3>
<div class="para"><p>If you wanted to find all the clients who are active and male you can stack the named scopes like this:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>You can call this new named_scope with <tt>Client.active.all</tt> and this will do the same query as if we just used <tt>Client.all(:conditions =&gt; ["active = ?", true])</tt>. If you want to find the first client within this named scope you could do <tt>Client.active.first</tt>.</p></div>
<h3 id="_combining_named_scopes">18.2. Combining Named Scopes</h3>
<div class="paragraph"><p>If you wanted to find all the clients who are active and male you can stack the named scopes like this:</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>Client<span style="color: #990000">.</span>males<span style="color: #990000">.</span>active<span style="color: #990000">.</span>all
</tt></pre></div></div>
<div class="para"><p>If you would then like to do a <tt>all</tt> on that scope, you can. Just like an association, named scopes allow you to call <tt>all</tt> on them:</p></div>
<pre><tt>Client<span style="color: #990000">.</span>males<span style="color: #990000">.</span>active<span style="color: #990000">.</span>all</tt></pre></div></div>
<div class="paragraph"><p>If you would then like to do a <tt>all</tt> on that scope, you can. Just like an association, named scopes allow you to call <tt>all</tt> on them:</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>Client<span style="color: #990000">.</span>males<span style="color: #990000">.</span>active<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">"age &gt; ?"</span><span style="color: #990000">,</span> params<span style="color: #990000">[:</span>age<span style="color: #990000">]])</span>
</tt></pre></div></div>
<h3 id="_runtime_evaluation_of_named_scope_conditions">17.3. Runtime Evaluation of Named Scope Conditions</h3>
<div class="para"><p>Consider the following code:</p></div>
<pre><tt>Client<span style="color: #990000">.</span>males<span style="color: #990000">.</span>active<span style="color: #990000">.</span>all<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">"age &gt; ?"</span><span style="color: #990000">,</span> params<span style="color: #990000">[:</span>age<span style="color: #990000">]])</span></tt></pre></div></div>
<h3 id="_runtime_evaluation_of_named_scope_conditions">18.3. Runtime Evaluation of Named Scope Conditions</h3>
<div class="paragraph"><p>Consider the following code:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -856,9 +913,8 @@ 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> Client <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
named_scope <span style="color: #990000">:</span>recent<span style="color: #990000">,</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>created_at <span style="color: #990000">&gt;</span> <span style="color: #993399">2</span><span style="color: #990000">.</span>weeks<span style="color: #990000">.</span>ago <span style="color: #FF0000">}</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>This looks like a standard named scope that defines a method called recent which gathers all records created any time between now and 2 weeks ago. That's correct for the first time the model is loaded but for any time after that, <tt>2.weeks.ago</tt> is set to that same value, so you will consistently get records from a certain date until your model is reloaded by something like your application restarting. The way to fix this is to put the code in a lambda block:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This looks like a standard named scope that defines a method called <tt>recent</tt> which gathers all records created any time between now and 2 weeks ago. That&#8217;s correct for the first time the model is loaded but for any time after that, <tt>2.weeks.ago</tt> is set to that same value, so you will consistently get records from a certain date until your model is reloaded by something like your application restarting. The way to fix this is to put the code in a lambda block:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -866,11 +922,10 @@ 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> Client <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
named_scope <span style="color: #990000">:</span>recent<span style="color: #990000">,</span> lambda <span style="color: #FF0000">{</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at &gt; ?"</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">.</span>weeks<span style="color: #990000">.</span>ago<span style="color: #990000">]</span> <span style="color: #FF0000">}</span> <span style="color: #FF0000">}</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>And now every time the recent named scope is called, the code in the lambda block will be parsed, so you'll get actually 2 weeks ago from the code execution, not 2 weeks ago from the time the model was loaded.</p></div>
<h3 id="_named_scopes_with_multiple_models">17.4. Named Scopes with Multiple Models</h3>
<div class="para"><p>In a named scope you can use <tt>:include</tt> and <tt>:joins</tt> options just like in find.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>And now every time the <tt>recent</tt> named scope is called, the code in the lambda block will be executed, so you&#8217;ll get actually 2 weeks ago from the code execution, not 2 weeks ago from the time the model was loaded.</p></div>
<h3 id="_named_scopes_with_multiple_models">18.4. Named Scopes with Multiple Models</h3>
<div class="paragraph"><p>In a named scope you can use <tt>:include</tt> and <tt>:joins</tt> options just like in <tt>find</tt>.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -879,11 +934,10 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Client <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
named_scope <span style="color: #990000">:</span>active_within_2_weeks<span style="color: #990000">,</span> <span style="color: #990000">:</span>joins <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>order<span style="color: #990000">,</span>
lambda <span style="color: #FF0000">{</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">"orders.created_at &gt; ?"</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">.</span>weeks<span style="color: #990000">.</span>ago<span style="color: #990000">]</span> <span style="color: #FF0000">}</span> <span style="color: #FF0000">}</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>This method, called as <tt>Client.active_within_2_weeks.all</tt>, will return all clients who have placed orders in the past 2 weeks.</p></div>
<h3 id="_arguments_to_named_scopes">17.5. Arguments to Named Scopes</h3>
<div class="para"><p>If you want to pass a named scope a compulsory argument, just specify it as a block parameter like this:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This method, called as <tt>Client.active_within_2_weeks.all</tt>, will return all clients who have placed orders in the past 2 weeks.</p></div>
<h3 id="_arguments_to_named_scopes">18.5. Arguments to Named Scopes</h3>
<div class="paragraph"><p>If you want to pass to a named scope a required arugment, just specify it as a block argument like this:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -891,9 +945,8 @@ 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> Client <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
named_scope <span style="color: #990000">:</span>recent<span style="color: #990000">,</span> lambda <span style="color: #FF0000">{</span> <span style="color: #990000">|</span>time<span style="color: #990000">|</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at &gt; ?"</span><span style="color: #990000">,</span> time<span style="color: #990000">]</span> <span style="color: #FF0000">}</span> <span style="color: #FF0000">}</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>This will work if you call <tt>Client.recent(2.weeks.ago).all</tt> but not if you call <tt>Client.recent</tt>. If you want to add an optional argument for this, you have to use the splat operator as the block's parameter.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This will work if you call <tt>Client.recent(2.weeks.ago).all</tt> but not if you call <tt>Client.recent</tt>. If you want to add an optional argument for this, you have to use prefix the arugment with an *.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -901,12 +954,11 @@ 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> Client <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
named_scope <span style="color: #990000">:</span>recent<span style="color: #990000">,</span> lambda <span style="color: #FF0000">{</span> <span style="color: #990000">|*</span>args<span style="color: #990000">|</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at &gt; ?"</span><span style="color: #990000">,</span> args<span style="color: #990000">.</span>first <span style="color: #990000">||</span> <span style="color: #993399">2</span><span style="color: #990000">.</span>weeks<span style="color: #990000">.</span>ago<span style="color: #990000">]</span> <span style="color: #FF0000">}</span> <span style="color: #FF0000">}</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>This will work with <tt>Client.recent(2.weeks.ago).all</tt> and <tt>Client.recent.all</tt>, with the latter always returning records with a created_at date between right now and 2 weeks ago.</p></div>
<div class="para"><p>Remember that named scopes are stackable, so you will be able to do <tt>Client.recent(2.weeks.ago).unlocked.all</tt> to find all clients created between right now and 2 weeks ago and have their locked field set to false.</p></div>
<h3 id="_anonymous_scopes">17.6. Anonymous Scopes</h3>
<div class="para"><p>All Active Record models come with a named scope named <tt>scoped</tt>, which allows you to create anonymous scopes. For example:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This will work with <tt>Client.recent(2.weeks.ago).all</tt> and <tt>Client.recent.all</tt>, with the latter always returning records with a created_at date between right now and 2 weeks ago.</p></div>
<div class="paragraph"><p>Remember that named scopes are stackable, so you will be able to do <tt>Client.recent(2.weeks.ago).unlocked.all</tt> to find all clients created between right now and 2 weeks ago and have their locked field set to false.</p></div>
<h3 id="_anonymous_scopes">18.6. Anonymous Scopes</h3>
<div class="paragraph"><p>All Active Record models come with a named scope named <tt>scoped</tt>, which allows you to create anonymous scopes. For example:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -916,29 +968,26 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>recent
scoped <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">"created_at &gt; ?"</span><span style="color: #990000">,</span> <span style="color: #993399">2</span><span style="color: #990000">.</span>weeks<span style="color: #990000">.</span>ago<span style="color: #990000">]</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>Anonymous scopes are most useful to create scopes "on the fly":</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Anonymous scopes are most useful to create scopes "on the fly":</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>Client<span style="color: #990000">.</span>scoped<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>gender <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"male"</span> <span style="color: #FF0000">}</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>Just like named scopes, anonymous scopes can be stacked, either with other anonymous scopes or with regular named scopes.</p></div>
<pre><tt>Client<span style="color: #990000">.</span>scoped<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>gender <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"male"</span> <span style="color: #FF0000">}</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>Just like named scopes, anonymous scopes can be stacked, either with other anonymous scopes or with regular named scopes.</p></div>
</div>
<h2 id="_existence_of_objects">18. Existence of Objects</h2>
<h2 id="_existence_of_objects">19. Existence of Objects</h2>
<div class="sectionbody">
<div class="para"><p>If you simply want to check for the existence of the object there's a method called <tt>exists?</tt>. This method will query the database using the same query as find, but instead of returning an object or collection of objects it will return either true or false.</p></div>
<div class="paragraph"><p>If you simply want to check for the existence of the object there&#8217;s a method called <tt>exists?</tt>. This method will query the database using the same query as <tt>find</tt>, but instead of returning an object or collection of objects it will return either <tt>true</tt> or false+.</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>Client<span style="color: #990000">.</span>exists?<span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>The above code will check for the existence of a clients table record with the id of 1 and return true if it exists.</p></div>
<pre><tt>Client<span style="color: #990000">.</span>exists?<span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>The <tt>exists?</tt> method also takes multiple ids, but the catch is that it will return true if any one of those records exists.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -946,46 +995,40 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>Client<span style="color: #990000">.</span>exists?<span style="color: #990000">(</span><span style="color: #993399">1</span><span style="color: #990000">,</span><span style="color: #993399">2</span><span style="color: #990000">,</span><span style="color: #993399">3</span><span style="color: #990000">)</span>
<span style="font-style: italic"><span style="color: #9A1900"># or</span></span>
Client<span style="color: #990000">.</span>exists?<span style="color: #990000">([</span><span style="color: #993399">1</span><span style="color: #990000">,</span><span style="color: #993399">2</span><span style="color: #990000">,</span><span style="color: #993399">3</span><span style="color: #990000">])</span>
</tt></pre></div></div>
<div class="para"><p>The <tt>exists?</tt> method also takes multiple ids, as shown by the above code, but the catch is that it will return true if any one of those records exists.</p></div>
<div class="para"><p>Further more, <tt>exists</tt> takes a <tt>conditions</tt> option much like find:</p></div>
Client<span style="color: #990000">.</span>exists?<span style="color: #990000">([</span><span style="color: #993399">1</span><span style="color: #990000">,</span><span style="color: #993399">2</span><span style="color: #990000">,</span><span style="color: #993399">3</span><span style="color: #990000">])</span></tt></pre></div></div>
<div class="paragraph"><p>Further more, <tt>exists</tt> takes a <tt>conditions</tt> option much like find:</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>Client<span style="color: #990000">.</span>exists?<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"first_name = 'Ryan'"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<pre><tt>Client<span style="color: #990000">.</span>exists?<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"first_name = 'Ryan'"</span><span style="color: #990000">)</span></tt></pre></div></div>
</div>
<h2 id="_calculations">19. Calculations</h2>
<h2 id="_calculations">20. Calculations</h2>
<div class="sectionbody">
<div class="para"><p>This section uses count as an example method in this preamble, but the options described apply to all sub-sections.</p></div>
<div class="para"><p><tt>count</tt> takes conditions much in the same way <tt>exists?</tt> does:</p></div>
<div class="paragraph"><p>This section uses count as an example method in this preamble, but the options described apply to all sub-sections.</p></div>
<div class="paragraph"><p><tt>count</tt> takes conditions much in the same way <tt>exists?</tt> does:</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>Client<span style="color: #990000">.</span>count<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"first_name = 'Ryan'"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>Which will execute:</p></div>
<pre><tt>Client<span style="color: #990000">.</span>count<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"first_name = 'Ryan'"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>Which will execute:</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">SELECT</span></span> count<span style="color: #990000">(*)</span> <span style="font-weight: bold"><span style="color: #0000FF">AS</span></span> count_all <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>first_name <span style="color: #990000">=</span> <span style="color: #993399">1</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>You can also use <tt>include</tt> or <tt>joins</tt> for this to do something a little more complex:</p></div>
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> count<span style="color: #990000">(*)</span> <span style="font-weight: bold"><span style="color: #0000FF">AS</span></span> count_all <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span> <span style="color: #990000">(</span>first_name <span style="color: #990000">=</span> <span style="color: #FF0000">'Ryan'</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>You can also use <tt>:include</tt> or <tt>:joins</tt> for this to do something a little more complex:</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>Client<span style="color: #990000">.</span>count<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"clients.first_name = 'Ryan' AND orders.status = 'received'"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"orders"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>Which will execute:</p></div>
<pre><tt>Client<span style="color: #990000">.</span>count<span style="color: #990000">(:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"clients.first_name = 'Ryan' AND orders.status = 'received'"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"orders"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>Which will execute:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -993,63 +1036,98 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">SELECT</span></span> count<span style="color: #990000">(</span><span style="font-weight: bold"><span style="color: #0000FF">DISTINCT</span></span> clients<span style="color: #990000">.</span>id<span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">AS</span></span> count_all <span style="font-weight: bold"><span style="color: #0000FF">FROM</span></span> clients
<span style="font-weight: bold"><span style="color: #0000FF">LEFT</span></span> <span style="font-weight: bold"><span style="color: #0000FF">OUTER</span></span> <span style="font-weight: bold"><span style="color: #0000FF">JOIN</span></span> orders <span style="font-weight: bold"><span style="color: #0000FF">ON</span></span> orders<span style="color: #990000">.</span>client_id <span style="color: #990000">=</span> client<span style="color: #990000">.</span>id <span style="font-weight: bold"><span style="color: #0000FF">WHERE</span></span>
<span style="color: #990000">(</span>clients<span style="color: #990000">.</span>first_name <span style="color: #990000">=</span> <span style="color: #FF0000">'name'</span> <span style="font-weight: bold"><span style="color: #0000FF">AND</span></span> orders<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">status</span></span> <span style="color: #990000">=</span> <span style="color: #FF0000">'received'</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>This code specifies <tt>clients.first_name</tt> just in case one of the join tables has a field also called <tt>first_name</tt> and it uses <tt>orders.status</tt> because that's the name of our join table.</p></div>
<h3 id="_count">19.1. Count</h3>
<div class="para"><p>If you want to see how many records are in your model's table you could call <tt>Client.count</tt> and that will return the number. If you want to be more specific and find all the clients with their age present in the database you can use <tt>Client.count(:age)</tt>.</p></div>
<div class="para"><p>For options, please see the parent section, Calculations.</p></div>
<h3 id="_average">19.2. Average</h3>
<div class="para"><p>If you want to see the average of a certain number in one of your tables you can call the <tt>average</tt> method on the class that relates to the table. This method call will look something like this:</p></div>
<span style="color: #990000">(</span>clients<span style="color: #990000">.</span>first_name <span style="color: #990000">=</span> <span style="color: #FF0000">'Ryan'</span> <span style="font-weight: bold"><span style="color: #0000FF">AND</span></span> orders<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">status</span></span> <span style="color: #990000">=</span> <span style="color: #FF0000">'received'</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>This code specifies <tt>clients.first_name</tt> just in case one of the join tables has a field also called <tt>first_name</tt> and it uses <tt>orders.status</tt> because that&#8217;s the name of our join table.</p></div>
<h3 id="_count">20.1. Count</h3>
<div class="paragraph"><p>If you want to see how many records are in your model&#8217;s table you could call <tt>Client.count</tt> and that will return the number. If you want to be more specific and find all the clients with their age present in the database you can use <tt>Client.count(:age)</tt>.</p></div>
<div class="paragraph"><p>For options, please see the parent section, <a href="#_calculations">Calculations</a>.</p></div>
<h3 id="_average">20.2. Average</h3>
<div class="paragraph"><p>If you want to see the average of a certain number in one of your tables you can call the <tt>average</tt> method on the class that relates to the table. This method call will look something like this:</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>Client<span style="color: #990000">.</span>average<span style="color: #990000">(</span><span style="color: #FF0000">"orders_count"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>This will return a number (possibly a floating point number such as 3.14159265) representing the average value in the field.</p></div>
<div class="para"><p>For options, please see the parent section, <a href="#_calculations">Calculations</a></p></div>
<h3 id="_minimum">19.3. Minimum</h3>
<div class="para"><p>If you want to find the minimum value of a field in your table you can call the <tt>minimum</tt> method on the class that relates to the table. This method call will look something like this:</p></div>
<pre><tt>Client<span style="color: #990000">.</span>average<span style="color: #990000">(</span><span style="color: #FF0000">"orders_count"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>This will return a number (possibly a floating point number such as 3.14159265) representing the average value in the field.</p></div>
<div class="paragraph"><p>For options, please see the parent section, <a href="#_calculations">Calculations</a>.</p></div>
<h3 id="_minimum">20.3. Minimum</h3>
<div class="paragraph"><p>If you want to find the minimum value of a field in your table you can call the <tt>minimum</tt> method on the class that relates to the table. This method call will look something like this:</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>Client<span style="color: #990000">.</span>minimum<span style="color: #990000">(</span><span style="color: #FF0000">"age"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>For options, please see the parent section, <a href="#_calculations">Calculations</a></p></div>
<h3 id="_maximum">19.4. Maximum</h3>
<div class="para"><p>If you want to find the maximum value of a field in your table you can call the <tt>maximum</tt> method on the class that relates to the table. This method call will look something like this:</p></div>
<pre><tt>Client<span style="color: #990000">.</span>minimum<span style="color: #990000">(</span><span style="color: #FF0000">"age"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>For options, please see the parent section, <a href="#_calculations">Calculations</a></p></div>
<h3 id="_maximum">20.4. Maximum</h3>
<div class="paragraph"><p>If you want to find the maximum value of a field in your table you can call the <tt>maximum</tt> method on the class that relates to the table. This method call will look something like this:</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>Client<span style="color: #990000">.</span>maximum<span style="color: #990000">(</span><span style="color: #FF0000">"age"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>For options, please see the parent section, <a href="#_calculations">Calculations</a></p></div>
<h3 id="_sum">19.5. Sum</h3>
<div class="para"><p>If you want to find the sum of a field for all records in your table you can call the <tt>sum</tt> method on the class that relates to the table. This method call will look something like this:</p></div>
<pre><tt>Client<span style="color: #990000">.</span>maximum<span style="color: #990000">(</span><span style="color: #FF0000">"age"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>For options, please see the parent section, <a href="#_calculations">Calculations</a></p></div>
<h3 id="_sum">20.5. Sum</h3>
<div class="paragraph"><p>If you want to find the sum of a field for all records in your table you can call the <tt>sum</tt> method on the class that relates to the table. This method call will look something like this:</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>Client<span style="color: #990000">.</span>sum<span style="color: #990000">(</span><span style="color: #FF0000">"orders_count"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
<div class="para"><p>For options, please see the parent section, <a href="#_calculations">Calculations</a></p></div>
<pre><tt>Client<span style="color: #990000">.</span>sum<span style="color: #990000">(</span><span style="color: #FF0000">"orders_count"</span><span style="color: #990000">)</span></tt></pre></div></div>
<div class="paragraph"><p>For options, please see the parent section, <a href="#_calculations">Calculations</a></p></div>
</div>
<h2 id="_credits">20. Credits</h2>
<h2 id="_credits">21. Credits</h2>
<div class="sectionbody">
<div class="para"><p>Thanks to Ryan Bates for his awesome screencast on named scope #108. The information within the named scope section is intentionally similar to it, and without the cast may have not been possible.</p></div>
<div class="para"><p>Thanks to Mike Gunderloy for his tips on creating this guide.</p></div>
<div class="paragraph"><p>Thanks to Ryan Bates for his awesome screencast on named scope #108. The information within the named scope section is intentionally similar to it, and without the cast may have not been possible.</p></div>
<div class="paragraph"><p>Thanks to Mike Gunderloy for his tips on creating this guide.</p></div>
</div>
<h2 id="_changelog">21. Changelog</h2>
<h2 id="_changelog">22. Changelog</h2>
<div class="sectionbody">
<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/16">Lighthouse ticket</a></p></div>
<div class="ilist"><ul>
<div class="paragraph"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/16">Lighthouse ticket</a></p></div>
<div class="ulist"><ul>
<li>
<p>
December 23 2008: Xavier Noria suggestions added! From <a href="http://rails.lighthouseapp.com/projects/16213/tickets/16-activerecord-finders#ticket-16-27">this ticket</a> and <a href="http://rails.lighthouseapp.com/projects/16213/tickets/16-activerecord-finders#ticket-16-28">this ticket</a> and <a href="http://rails.lighthouseapp.com/projects/16213/tickets/16-activerecord-finders#ticket-16-29">this ticket</a>
</p>
</li>
<li>
<p>
December 22 2008: Added section on having.
</p>
</li>
<li>
<p>
December 22 2008: Added description of how to make hash conditions use an IN expression <a href="http://rails.loglibrary.com/chats/15279234">mentioned here</a>
</p>
</li>
<li>
<p>
December 22 2008: Mentioned using SQL as values for the lock option as mentioned in <a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/16-activerecord-finders#ticket-16-24">this ticket</a>
</p>
</li>
<li>
<p>
December 21 2008: Fixed <a href="http://rails.lighthouseapp.com/projects/16213/tickets/16-activerecord-finders#ticket-16-22">this ticket</a> minus two points; the lock SQL syntax and the having option.
</p>
</li>
<li>
<p>
December 21 2008: Added more to the has conditions section.
</p>
</li>
<li>
<p>
December 17 2008: Fixed up syntax errors.
</p>
</li>
<li>
<p>
December 16 2008: Covered hash conditions that were introduced in Rails 2.2.2.
</p>
</li>
<li>
<p>
December 1 2008: Added using an SQL function example to Selecting Certain Fields section as per <a href="http://rails.lighthouseapp.com/projects/16213/tickets/36-adding-an-example-for-using-distinct-to-ar-finders">this ticket</a>

View File

@@ -226,7 +226,23 @@ ul#navMain {
<li><a href="#_the_select_tag_and_options">The select tag and options</a></li>
<li><a href="#_select_boxes_for_dealing_with_models">Select boxes for dealing with models</a></li>
<li><a href="#_select_helpers_for_dealing_with_models">Select helpers for dealing with models</a></li>
<li><a href="#_option_tags_from_a_collection_of_arbitrary_objects">Option tags from a collection of arbitrary objects</a></li>
<li><a href="#_time_zone_and_country_select">Time zone and country select</a></li>
</ul>
</li>
<li>
<a href="#_miscellaneous">Miscellaneous</a>
<ul>
<li><a href="#_file_upload_form">File upload form</a></li>
<li><a href="#_scoping_out_form_controls_with_tt_fields_for_tt">Scoping out form controls with <tt>fields_for</tt></a></li>
<li><a href="#_making_custom_form_builders">Making custom form builders</a></li>
</ul>
</li>
@@ -237,9 +253,9 @@ ul#navMain {
<h1>Rails form helpers</h1>
<div id="preamble">
<div class="sectionbody">
<div class="para"><p>Forms in web applications are an essential interface for user input. However, form markup can quickly become tedious to write and maintain because of form control naming and their numerous attributes. Rails deals away with these complexities by providing view helpers for generating form markup. However, since they have different use-cases, developers are required to know all the differences between similar helper methods before putting them to use.</p></div>
<div class="para"><p>In this guide we will:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>Forms in web applications are an essential interface for user input. However, form markup can quickly become tedious to write and maintain because of form control naming and their numerous attributes. Rails deals away with these complexities by providing view helpers for generating form markup. However, since they have different use-cases, developers are required to know all the differences between similar helper methods before putting them to use.</p></div>
<div class="paragraph"><p>In this guide we will:</p></div>
<div class="ulist"><ul>
<li>
<p>
Create search forms and similar kind of generic forms not representing any specific model in your application;
@@ -278,16 +294,16 @@ Build complex, multi-model forms.
</div>
<h2 id="_basic_forms">1. Basic forms</h2>
<div class="sectionbody">
<div class="para"><p>The most basic form helper is <tt>form_tag</tt>.</p></div>
<div class="paragraph"><p>The most basic form helper is <tt>form_tag</tt>.</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;% form_tag do %&gt;
Form contents
&lt;% end %&gt;</tt></pre>
</div></div>
<div class="para"><p>When called without arguments like this, it creates a form element that has the current page for action attribute and "POST" as method (some line breaks added for readability):</p></div>
<div class="paragraph"><p>When called without arguments like this, it creates a form element that has the current page for action attribute and "POST" as method (some line breaks added for readability):</p></div>
<div class="listingblock">
<div class="title">Example: Sample rendering of <tt>form_tag</tt></div>
<div class="title">Sample rendering of <tt>form_tag</tt></div>
<div class="content">
<pre><tt>&lt;form action="/home/index" method="post"&gt;
&lt;div style="margin:0;padding:0"&gt;
@@ -296,7 +312,7 @@ Build complex, multi-model forms.
Form contents
&lt;/form&gt;</tt></pre>
</div></div>
<div class="para"><p>If you carefully observe this output, you can see that the helper generated something we didn't specify: a <tt>div</tt> element with a hidden input inside. This is a security feature of Rails called <strong>cross-site request forgery protection</strong> and form helpers generate it for every form which action isn't "GET" (provided that this security feature is enabled).</p></div>
<div class="paragraph"><p>If you carefully observe this output, you can see that the helper generated something we didn&#8217;t specify: a <tt>div</tt> element with a hidden input inside. This is a security feature of Rails called <strong>cross-site request forgery protection</strong> and form helpers generate it for every form which action isn&#8217;t "GET" (provided that this security feature is enabled).</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -306,7 +322,7 @@ Build complex, multi-model forms.
</tr></table>
</div>
<h3 id="_generic_search_form">1.1. Generic search form</h3>
<div class="para"><p>Probably the most minimal form often seen on the web is a search form with a single text input for search terms. This form consists of:</p></div>
<div class="paragraph"><p>Probably the most minimal form often seen on the web is a search form with a single text input for search terms. This form consists of:</p></div>
<div class="olist"><ol>
<li>
<p>
@@ -337,9 +353,9 @@ a submit element.
<td class="content">Always use "GET" as the method for search forms. Benefits are many: users are able to bookmark a specific search and get back to it; browsers cache results of "GET" requests, but not "POST"; and other.</td>
</tr></table>
</div>
<div class="para"><p>To create that, we will use <tt>form_tag</tt>, <tt>label_tag</tt>, <tt>text_field_tag</tt> and <tt>submit_tag</tt>, respectively.</p></div>
<div class="paragraph"><p>To create that, we will use <tt>form_tag</tt>, <tt>label_tag</tt>, <tt>text_field_tag</tt> and <tt>submit_tag</tt>, respectively.</p></div>
<div class="listingblock">
<div class="title">Example: A basic search form</div>
<div class="title">A basic search form</div>
<div class="content">
<pre><tt>&lt;% form_tag(search_path, :method =&gt; "get") do %&gt;
&lt;%= label_tag(:q, "Search for:") %&gt;
@@ -353,7 +369,7 @@ a submit element.
<img src="./images/icons/tip.png" alt="Tip" />
</td>
<td class="content">
<div class="para"><p><tt>search_path</tt> can be a named route specified in "routes.rb":</p></div>
<div class="paragraph"><p><tt>search_path</tt> can be a named route specified in "routes.rb":</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>map.search "search", :controller =&gt; "search"</tt></pre>
@@ -361,9 +377,9 @@ a submit element.
</td>
</tr></table>
</div>
<div class="para"><p>The above view code will result in the following markup:</p></div>
<div class="paragraph"><p>The above view code will result in the following markup:</p></div>
<div class="listingblock">
<div class="title">Example: Search form HTML</div>
<div class="title">Search form HTML</div>
<div class="content">
<pre><tt>&lt;form action="/search" method="get"&gt;
&lt;label for="q"&gt;Search for:&lt;/label&gt;
@@ -371,7 +387,7 @@ a submit element.
&lt;input name="commit" type="submit" value="Search" /&gt;
&lt;/form&gt;</tt></pre>
</div></div>
<div class="para"><p>Besides <tt>text_field_tag</tt> and <tt>submit_tag</tt>, there is a similar helper for <em>every</em> form control in HTML.</p></div>
<div class="paragraph"><p>Besides <tt>text_field_tag</tt> and <tt>submit_tag</tt>, there is a similar helper for <em>every</em> form control in HTML.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -381,22 +397,22 @@ a submit element.
</tr></table>
</div>
<h3 id="_multiple_hashes_in_form_helper_attributes">1.2. Multiple hashes in form helper attributes</h3>
<div class="para"><p>By now we've seen that the <tt>form_tag</tt> helper accepts 2 arguments: the path for the action attribute and an options hash for parameters (like <tt>:method</tt>).</p></div>
<div class="para"><p>Identical to the <tt>link_to</tt> helper, the path argument doesn't have to be given as string or a named route. It can be a hash of URL parameters that Rails' routing mechanism will turn into a valid URL. Still, we cannot simply write this:</p></div>
<div class="paragraph"><p>By now we&#8217;ve seen that the <tt>form_tag</tt> helper accepts 2 arguments: the path for the action attribute and an options hash for parameters (like <tt>:method</tt>).</p></div>
<div class="paragraph"><p>Identical to the &#8216;link_to` helper, the path argument doesn&#8217;t have to be given as string or a named route. It can be a hash of URL parameters that Rails&#8217; routing mechanism will turn into a valid URL. Still, we cannot simply write this:</p></div>
<div class="listingblock">
<div class="title">Example: A bad way to pass multiple hashes as method arguments</div>
<div class="title">A bad way to pass multiple hashes as method arguments</div>
<div class="content">
<pre><tt>form_tag(:controller =&gt; "people", :action =&gt; "search", :method =&gt; "get")
# =&gt; &lt;form action="/people/search?method=get" method="post"&gt;</tt></pre>
</div></div>
<div class="para"><p>Here we wanted to pass two hashes, but the Ruby interpreter sees only one hash, so Rails will construct a URL that we didn't want. The solution is to delimit the first hash (or both hashes) with curly brackets:</p></div>
<div class="paragraph"><p>Here we wanted to pass two hashes, but the Ruby interpreter sees only one hash, so Rails will construct a URL that we didn&#8217;t want. The solution is to delimit the first hash (or both hashes) with curly brackets:</p></div>
<div class="listingblock">
<div class="title">Example: The correct way of passing multiple hashes as arguments</div>
<div class="title">The correct way of passing multiple hashes as arguments</div>
<div class="content">
<pre><tt>form_tag({:controller =&gt; "people", :action =&gt; "search"}, :method =&gt; "get")
# =&gt; &lt;form action="/people/search" method="get"&gt;</tt></pre>
</div></div>
<div class="para"><p>This is a common pitfall when using form helpers, since many of them accept multiple hashes. So in future, if a helper produces unexpected output, make sure that you have delimited the hash parameters properly.</p></div>
<div class="paragraph"><p>This is a common pitfall when using form helpers, since many of them accept multiple hashes. So in future, if a helper produces unexpected output, make sure that you have delimited the hash parameters properly.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -406,7 +422,7 @@ a submit element.
</tr></table>
</div>
<h3 id="_checkboxes_radio_buttons_and_other_controls">1.3. Checkboxes, radio buttons and other controls</h3>
<div class="para"><p>Checkboxes are form controls that give the user a set of options they can enable or disable:</p></div>
<div class="paragraph"><p>Checkboxes are form controls that give the user a set of options they can enable or disable:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= check_box_tag(:pet_dog) %&gt;
@@ -421,7 +437,7 @@ output:
&lt;input id="pet_cat" name="pet_cat" type="checkbox" value="1" /&gt;
&lt;label for="pet_cat"&gt;I own a cat&lt;/label&gt;</tt></pre>
</div></div>
<div class="para"><p>Radio buttons, while similar to checkboxes, are controls that specify a set of options in which they are mutually exclusive (user can only pick one):</p></div>
<div class="paragraph"><p>Radio buttons, while similar to checkboxes, are controls that specify a set of options in which they are mutually exclusive (user can only pick one):</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= radio_button_tag(:age, "child") %&gt;
@@ -444,7 +460,7 @@ output:
<td class="content">Always use labels for each checkbox and radio button. They associate text with a specific option and provide a larger clickable region.</td>
</tr></table>
</div>
<div class="para"><p>Other form controls we might mention are the text area, password input and hidden input:</p></div>
<div class="paragraph"><p>Other form controls we might mention are the text area, password input and hidden input:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= text_area_tag(:message, "Hi, nice site", :size =&gt; "24x6") %&gt;
@@ -457,18 +473,18 @@ output:
&lt;input id="password" name="password" type="password" /&gt;
&lt;input id="parent_id" name="parent_id" type="hidden" value="5" /&gt;</tt></pre>
</div></div>
<div class="para"><p>Hidden inputs are not shown to the user, but they hold data same as any textual input. Values inside them can be changed with JavaScript.</p></div>
<div class="paragraph"><p>Hidden inputs are not shown to the user, but they hold data same as any textual input. Values inside them can be changed with JavaScript.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip" />
</td>
<td class="content">If you're using password input fields (for any purpose), you might want to prevent their values showing up in application logs by activating <tt>filter_parameter_logging(:password)</tt> in your ApplicationController.</td>
<td class="content">If you&#8217;re using password input fields (for any purpose), you might want to prevent their values showing up in application logs by activating <tt>filter_parameter_logging(:password)</tt> in your ApplicationController.</td>
</tr></table>
</div>
<h3 id="_how_do_forms_with_put_or_delete_methods_work">1.4. How do forms with PUT or DELETE methods work?</h3>
<div class="para"><p>Rails framework encourages RESTful design of your applications, which means you'll be making a lot of "PUT" and "DELETE" requests (besides "GET" and "POST"). Still, most browsers <em>don't support</em> methods other than "GET" and "POST" when it comes to submitting forms. How does this work, then?</p></div>
<div class="para"><p>Rails works around this issue by emulating other methods over POST with a hidden input named <tt>"_method"</tt> that is set to reflect the wanted method:</p></div>
<div class="paragraph"><p>Rails framework encourages RESTful design of your applications, which means you&#8217;ll be making a lot of "PUT" and "DELETE" requests (besides "GET" and "POST"). Still, most browsers <em>don&#8217;t support</em> methods other than "GET" and "POST" when it comes to submitting forms. How does this work, then?</p></div>
<div class="paragraph"><p>Rails works around this issue by emulating other methods over POST with a hidden input named <tt>"_method"</tt> that is set to reflect the wanted method:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>form_tag(search_path, :method =&gt; "put")
@@ -482,21 +498,21 @@ output:
&lt;/div&gt;
...</tt></pre>
</div></div>
<div class="para"><p>When parsing POSTed data, Rails will take into account the special <tt>"_method"</tt> parameter and act as if the HTTP method was the one specified inside it ("PUT" in this example).</p></div>
<div class="paragraph"><p>When parsing POSTed data, Rails will take into account the special <tt>"_method"</tt> parameter and act as if the HTTP method was the one specified inside it ("PUT" in this example).</p></div>
</div>
<h2 id="_forms_that_deal_with_model_attributes">2. Forms that deal with model attributes</h2>
<div class="sectionbody">
<div class="para"><p>When we're dealing with an actual model, we will use a different set of form helpers and have Rails take care of some details in the background. In the following examples we will handle an Article model. First, let us have the controller create one:</p></div>
<div class="paragraph"><p>When we&#8217;re dealing with an actual model, we will use a different set of form helpers and have Rails take care of some details in the background. In the following examples we will handle an Article model. First, let us have the controller create one:</p></div>
<div class="listingblock">
<div class="title">Example: articles_controller.rb</div>
<div class="title">articles_controller.rb</div>
<div class="content">
<pre><tt>def new
@article = Article.new
end</tt></pre>
</div></div>
<div class="para"><p>Now we switch to the view. The first thing to remember is that we should use <tt>form_for</tt> helper instead of <tt>form_tag</tt>, and that we should pass the model name and object as arguments:</p></div>
<div class="paragraph"><p>Now we switch to the view. The first thing to remember is that we should use <tt>form_for</tt> helper instead of <tt>form_tag</tt>, and that we should pass the model name and object as arguments:</p></div>
<div class="listingblock">
<div class="title">Example: articles/new.html.erb</div>
<div class="title">articles/new.html.erb</div>
<div class="content">
<pre><tt>&lt;% form_for :article, @article, :url =&gt; { :action =&gt; "create" } do |f| %&gt;
&lt;%= f.text_field :title %&gt;
@@ -504,7 +520,7 @@ end</tt></pre>
&lt;%= submit_tag "Create" %&gt;
&lt;% end %&gt;</tt></pre>
</div></div>
<div class="para"><p>There are a few things to note here:</p></div>
<div class="paragraph"><p>There are a few things to note here:</p></div>
<div class="olist"><ol>
<li>
<p>
@@ -527,7 +543,7 @@ Methods to create form controls are called <strong>on</strong> the form builder
</p>
</li>
</ol></div>
<div class="para"><p>The resulting HTML is:</p></div>
<div class="paragraph"><p>The resulting HTML is:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;form action="/articles/create" method="post"&gt;
@@ -536,19 +552,19 @@ Methods to create form controls are called <strong>on</strong> the form builder
&lt;input name="commit" type="submit" value="Create" /&gt;
&lt;/form&gt;</tt></pre>
</div></div>
<div class="para"><p>A nice thing about <tt>f.text_field</tt> and other helper methods is that they will pre-fill the form control with the value read from the corresponding attribute in the model. For example, if we created the article instance by supplying an initial value for the title in the controller:</p></div>
<div class="paragraph"><p>A nice thing about <tt>f.text_field</tt> and other helper methods is that they will pre-fill the form control with the value read from the corresponding attribute in the model. For example, if we created the article instance by supplying an initial value for the title in the controller:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>@article = Article.new(:title =&gt; "Rails makes forms easy")</tt></pre>
</div></div>
<div class="para"><p>&#8230; the corresponding input will be rendered with a value:</p></div>
<div class="paragraph"><p>... the corresponding input will be rendered with a value:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;input id="post_title" name="post[title]" size="30" type="text" value="Rails makes forms easy" /&gt;</tt></pre>
</div></div>
<h3 id="_relying_on_record_identification">2.1. Relying on record identification</h3>
<div class="para"><p>In the previous chapter we handled the Article model. This model is directly available to users of our application and, following the best practices for developing with Rails, we should declare it <strong>a resource</strong>.</p></div>
<div class="para"><p>When dealing with RESTful resources, our calls to <tt>form_for</tt> can get significantly easier if we rely on <strong>record identification</strong>. In short, we can just pass the model instance and have Rails figure out model name and the rest:</p></div>
<div class="paragraph"><p>In the previous chapter we handled the Article model. This model is directly available to users of our application, so&#8201;&#8212;&#8201;following the best practices for developing with Rails&#8201;&#8212;&#8201;we should declare it <strong>a resource</strong>.</p></div>
<div class="paragraph"><p>When dealing with RESTful resources, our calls to <tt>form_for</tt> can get significantly easier if we rely on <strong>record identification</strong>. In short, we can just pass the model instance and have Rails figure out model name and the rest:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>## Creating a new article
@@ -563,20 +579,20 @@ form_for(:article, @article, :url =&gt; article_path(@article), :method =&gt; "p
# short-style:
form_for(@article)</tt></pre>
</div></div>
<div class="para"><p>Notice how the short-style <tt>form_for</tt> invocation is conveniently the same, regardless of the record being new or existing. Record identification is smart enough to figure out if the record is new by asking <tt>record.new_record?</tt>.</p></div>
<div class="paragraph"><p>Notice how the short-style <tt>form_for</tt> invocation is conveniently the same, regardless of the record being new or existing. Record identification is smart enough to figure out if the record is new by asking <tt>record.new_record?</tt>.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/warning.png" alt="Warning" />
</td>
<td class="content">When you're using STI (single-table inheritance) with your models, you can't rely on record identification on a subclass if only their parent class is declared a resource. You will have to specify the model name, <tt>:url</tt> and <tt>:method</tt> explicitly.</td>
<td class="content">When you&#8217;re using STI (single-table inheritance) with your models, you can&#8217;t rely on record identification on a subclass if only their parent class is declared a resource. You will have to specify the model name, <tt>:url</tt> and <tt>:method</tt> explicitly.</td>
</tr></table>
</div>
</div>
<h2 id="_making_select_boxes_with_ease">3. Making select boxes with ease</h2>
<div class="sectionbody">
<div class="para"><p>Select boxes in HTML require a significant amount of markup (one <tt>OPTION</tt> element for each option to choose from), therefore it makes the most sense for them to be dynamically generated from data stored in arrays or hashes.</p></div>
<div class="para"><p>Here is what our wanted markup might look like:</p></div>
<div class="paragraph"><p>Select boxes in HTML require a significant amount of markup (one <tt>OPTION</tt> element for each option to choose from), therefore it makes the most sense for them to be dynamically generated from data stored in arrays or hashes.</p></div>
<div class="paragraph"><p>Here is what our wanted markup might look like:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;select name="city_id" id="city_id"&gt;
@@ -586,15 +602,14 @@ form_for(@article)</tt></pre>
&lt;option value="12"&gt;Berlin&lt;/option&gt;
&lt;/select&gt;</tt></pre>
</div></div>
<div class="para"><p>Here we have a list of cities where their names are presented to the user, but internally we want to handle just their IDs so we keep them in value attributes. Let's see how Rails can help out here.</p></div>
<div class="paragraph"><p>Here we have a list of cities where their names are presented to the user, but internally we want to handle just their IDs so we keep them in value attributes. Let&#8217;s see how Rails can help out here.</p></div>
<h3 id="_the_select_tag_and_options">3.1. The select tag and options</h3>
<div class="para"><p>The most generic helper is <tt>select_tag</tt>, which &#8212; as the name implies &#8212; simply generates the <tt>SELECT</tt> tag that encapsulates the options:</p></div>
<div class="paragraph"><p>The most generic helper is <tt>select_tag</tt>, which&#8201;&#8212;&#8201;as the name implies&#8201;&#8212;&#8201;simply generates the <tt>SELECT</tt> tag that encapsulates an options string:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= select_tag(:city_id, '&lt;option value="1"&gt;Lisabon&lt;/option&gt;...') %&gt;</tt></pre>
</div></div>
<div class="para"><p>This is a start, but it doesn't dynamically create our option tags. We had to pass them in as a string.</p></div>
<div class="para"><p>We can generate option tags with the <tt>options_for_select</tt> helper:</p></div>
<div class="paragraph"><p>This is a start, but it doesn&#8217;t dynamically create our option tags. We can generate option tags with the <tt>options_for_select</tt> helper:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= options_for_select([['Lisabon', 1], ['Madrid', 2], ...]) %&gt;
@@ -605,13 +620,13 @@ output:
&lt;option value="2"&gt;Madrid&lt;/option&gt;
...</tt></pre>
</div></div>
<div class="para"><p>For input data we used a nested array where each element has two elements: visible value (name) and internal value (ID).</p></div>
<div class="para"><p>Now you can combine <tt>select_tag</tt> and <tt>options_for_select</tt> to achieve the desired, complete markup:</p></div>
<div class="paragraph"><p>For input data we used a nested array where each item has two elements: option text (city name) and option value (city id).</p></div>
<div class="paragraph"><p>Knowing this, you can combine <tt>select_tag</tt> and <tt>options_for_select</tt> to achieve the desired, complete markup:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= select_tag(:city_id, options_for_select(...)) %&gt;</tt></pre>
</div></div>
<div class="para"><p>Sometimes, depending on our application's needs, we also wish a specific option to be pre-selected. The <tt>options_for_select</tt> helper supports this with an optional second argument:</p></div>
<div class="paragraph"><p>Sometimes, depending on our application&#8217;s needs, we also wish a specific option to be pre-selected. The <tt>options_for_select</tt> helper supports this with an optional second argument:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= options_for_select(cities_array, 2) %&gt;
@@ -622,14 +637,95 @@ output:
&lt;option value="2" selected="selected"&gt;Madrid&lt;/option&gt;
...</tt></pre>
</div></div>
<div class="para"><p>So whenever Rails sees that the internal value of an option being generated matches this value, it will add the <tt>selected</tt> attribute to that option.</p></div>
<h3 id="_select_boxes_for_dealing_with_models">3.2. Select boxes for dealing with models</h3>
<div class="para"><p>Until now we've covered how to make generic select boxes, but in most cases our form controls will be tied to a specific database model. So, to continue from our previous examples, let's assume that we have a "Person" model with a <tt>city_id</tt> attribute.</p></div>
<div class="paragraph"><p>So whenever Rails sees that the internal value of an option being generated matches this value, it will add the <tt>selected</tt> attribute to that option.</p></div>
<h3 id="_select_helpers_for_dealing_with_models">3.2. Select helpers for dealing with models</h3>
<div class="paragraph"><p>Until now we&#8217;ve covered how to make generic select boxes, but in most cases our form controls will be tied to a specific database model. So, to continue from our previous examples, let&#8217;s assume that we have a "Person" model with a <tt>city_id</tt> attribute.</p></div>
<div class="paragraph"><p>Consistent with other form helpers, when dealing with models we drop the <tt>"_tag"</tt> suffix from <tt>select_tag</tt> that we used in previous examples:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>...</tt></pre>
<pre><tt># controller:
@person = Person.new(:city_id =&gt; 2)
# view:
&lt;%= select(:person, :city_id, [['Lisabon', 1], ['Madrid', 2], ...]) %&gt;</tt></pre>
</div></div>
<div class="paragraph"><p>Notice that the third parameter, the options array, is the same kind of argument we pass to <tt>options_for_select</tt>. One thing that we have as an advantage here is that we don&#8217;t have to worry about pre-selecting the correct city if the user already has one&#8201;&#8212;&#8201;Rails will do this for us by reading from <tt>@person.city_id</tt> attribute.</p></div>
<div class="paragraph"><p>As before, if we were to use <tt>select</tt> helper on a form builder scoped to <tt>@person</tt> object, the syntax would be:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt># select on a form builder
&lt;%= f.select(:city_id, ...) %&gt;</tt></pre>
</div></div>
<h3 id="_option_tags_from_a_collection_of_arbitrary_objects">3.3. Option tags from a collection of arbitrary objects</h3>
<div class="paragraph"><p>Until now we were generating option tags from nested arrays with the help of <tt>options_for_select</tt> method. Data in our array were raw values:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= options_for_select([['Lisabon', 1], ['Madrid', 2], ...]) %&gt;</tt></pre>
</div></div>
<div class="paragraph"><p>But what if we had a <strong>City</strong> model (perhaps an ActiveRecord one) and we wanted to generate option tags from a collection of those objects? One solution would be to make a nested array by iterating over them:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;% cities_array = City.find(:all).map { |city| [city.name, city.id] } %&gt;
&lt;%= options_for_select(cities_array) %&gt;</tt></pre>
</div></div>
<div class="paragraph"><p>This is a perfectly valid solution, but Rails provides us with a less verbose alternative: <tt>options_from_collection_for_select</tt>. This helper expects a collection of arbitrary objects and two additional arguments: the names of the methods to read the option <strong>value</strong> and <strong>text</strong> from, respectively:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= options_from_collection_for_select(City.all, :id, :name) %&gt;</tt></pre>
</div></div>
<div class="paragraph"><p>As the name implies, this only generates option tags. A method to go along with it is <tt>collection_select</tt>:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= collection_select(:person, :city_id, City.all, :id, :name) %&gt;</tt></pre>
</div></div>
<div class="paragraph"><p>To recap, <tt>options_from_collection_for_select</tt> are to <tt>collection_select</tt> what <tt>options_for_select</tt> are to <tt>select</tt>.</p></div>
<h3 id="_time_zone_and_country_select">3.4. Time zone and country select</h3>
<div class="paragraph"><p>To leverage time zone support in Rails, we have to ask our users what time zone they are in. Doing so would require generating select options from a list of pre-defined TimeZone objects using <tt>collection_select</tt>, but we can simply use the <tt>time_zone_select</tt> helper that already wraps this:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= time_zone_select(:person, :city_id) %&gt;</tt></pre>
</div></div>
<div class="paragraph"><p>There is also <tt>time_zone_options_for_select</tt> helper for a more manual (therefore more customizable) way of doing this. Read the API documentation to learn about the possible arguments for these two methods.</p></div>
<div class="paragraph"><p>When it comes to country select, Rails <em>used</em> to have the built-in helper <tt>country_select</tt> but was extracted to a plugin.
TODO: plugin URL</p></div>
</div>
<h2 id="_miscellaneous">4. Miscellaneous</h2>
<div class="sectionbody">
<h3 id="_file_upload_form">4.1. File upload form</h3>
<div class="paragraph"><p>:multipart - If set to true, the enctype is set to "multipart/form-data".</p></div>
<h3 id="_scoping_out_form_controls_with_tt_fields_for_tt">4.2. Scoping out form controls with <tt>fields_for</tt></h3>
<div class="paragraph"><p>Creates a scope around a specific model object like <tt>form_for</tt>, but doesnt create the form tags themselves. This makes <tt>fields_for</tt> suitable for specifying additional model objects in the same form:</p></div>
<h3 id="_making_custom_form_builders">4.3. Making custom form builders</h3>
<div class="paragraph"><p>You can also build forms using a customized FormBuilder class. Subclass FormBuilder and override or define some more helpers, then use your custom builder. For example, lets say you made a helper to automatically add labels to form inputs.</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;% form_for :person, @person, :url =&gt; { :action =&gt; "update" }, :builder =&gt; LabellingFormBuilder do |f| %&gt;
&lt;%= f.text_field :first_name %&gt;
&lt;%= f.text_field :last_name %&gt;
&lt;%= text_area :person, :biography %&gt;
&lt;%= check_box_tag "person[admin]", @person.company.admin? %&gt;
&lt;% end %&gt;</tt></pre>
</div></div>
<div class="ulist"><ul>
<li>
<p>
<tt>form_for</tt> within a namespace
</p>
</li>
</ul></div>
<div class="listingblock">
<div class="content">
<pre><tt>select_tag(name, option_tags = nil, html_options = { :multiple, :disabled })
select(object, method, choices, options = {}, html_options = {})
options_for_select(container, selected = nil)
collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
options_from_collection_for_select(collection, value_method, text_method, selected = nil)
time_zone_options_for_select(selected = nil, priority_zones = nil, model = ::ActiveSupport::TimeZone)
time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})</tt></pre>
</div></div>
<div class="para"><p>&#8230;</p></div>
</div>
</div>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Ruby on Rails guides</title>
<title>Ruby on Rails Guides</title>
<!--[if lt IE 8]>
<script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script>
<![endif]-->
@@ -196,9 +196,22 @@ ul#navMain {
<div id="container" class="notoc">
<div id="content">
<h1>Ruby on Rails guides</h1>
<h1>Ruby on Rails Guides</h1>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph"><p>These guides are designed to make you immediately productive with Rails, and to help you understand how all of the pieces fit together. There are two different versions of the Guides site, and you should be sure to use the one that applies to your situation:</p></div>
<div class="ulist"><ul>
<li>
<p>
<a href="http://guides.rubyonrails.org/">Current Release version</a> - based on Rails 2.2
</p>
</li>
<li>
<p>
<a href="http://guides.rails.info/">Edge Rails version</a> - based on the Rails 2.3 branch
</p>
</li>
</ul></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -219,18 +232,18 @@ ul#navMain {
<div class="sidebarblock">
<div class="sidebar-content">
<div class="sidebar-title"><a href="getting_started_with_rails.html">Getting Started with Rails</a></div>
<div class="para"><p>Everything you need to know to install Rails and create your first application.</p></div>
<div class="paragraph"><p>Everything you need to know to install Rails and create your first application.</p></div>
</div></div>
<h2>Models</h2>
<div class="sidebarblock">
<div class="sidebar-content">
<div class="sidebar-title"><a href="migrations.html">Rails Database Migrations</a></div>
<div class="para"><p>This guide covers how you can use Active Record migrations to alter your database in a structured and organized manner.</p></div>
<div class="paragraph"><p>This guide covers how you can use Active Record migrations to alter your database in a structured and organized manner.</p></div>
</div></div>
<div class="sidebarblock">
<div class="sidebar-content">
<div class="sidebar-title"><a href="association_basics.html">Active Record Associations</a></div>
<div class="para"><p>This guide covers all the associations provided by Active Record.</p></div>
<div class="paragraph"><p>This guide covers all the associations provided by Active Record.</p></div>
</div></div>
<div class="sidebarblock">
<div class="sidebar-content">
@@ -243,13 +256,13 @@ ul#navMain {
<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/16">Lighthouse Ticket</a></td>
</tr></table>
</div>
<div class="para"><p>This guide covers the find method defined in ActiveRecord::Base, as well as named scopes.</p></div>
<div class="paragraph"><p>This guide covers the find method defined in ActiveRecord::Base, as well as named scopes.</p></div>
</div></div>
<h2>Views</h2>
<div class="sidebarblock">
<div class="sidebar-content">
<div class="sidebar-title"><a href="layouts_and_rendering.html">Layouts and Rendering in Rails</a></div>
<div class="para"><p>This guide covers the basic layout features of Action Controller and Action View,
<div class="paragraph"><p>This guide covers the basic layout features of Action Controller and Action View,
including rendering and redirecting, using <tt>content_for</tt> blocks, and working
with partials.</p></div>
</div></div>
@@ -264,19 +277,19 @@ with partials.</p></div>
<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/1">Lighthouse Ticket</a></td>
</tr></table>
</div>
<div class="para"><p>Guide to using built in Form helpers.</p></div>
<div class="paragraph"><p>Guide to using built in Form helpers.</p></div>
</div></div>
<h2>Controllers</h2>
<div class="sidebarblock">
<div class="sidebar-content">
<div class="sidebar-title"><a href="routing_outside_in.html">Rails Routing from the Outside In</a></div>
<div class="para"><p>This guide covers the user-facing features of Rails routing. If you want to
<div class="paragraph"><p>This guide covers the user-facing features of Rails routing. If you want to
understand how to use routing in your own Rails applications, start here.</p></div>
</div></div>
<div class="sidebarblock">
<div class="sidebar-content">
<div class="sidebar-title"><a href="actioncontroller_basics.html">Basics of Action Controller</a></div>
<div class="para"><p>This guide covers how controllers work and how they fit into the request cycle in your application. It includes sessions, filters, and cookies, data streaming, and dealing with exceptions raised by a request, among other topics.</p></div>
<div class="paragraph"><p>This guide covers how controllers work and how they fit into the request cycle in your application. It includes sessions, filters, and cookies, data streaming, and dealing with exceptions raised by a request, among other topics.</p></div>
</div></div>
<div class="sidebarblock">
<div class="sidebar-content">
@@ -289,7 +302,7 @@ understand how to use routing in your own Rails applications, start here.</p></d
<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/10">Lighthouse Ticket</a></td>
</tr></table>
</div>
<div class="para"><p>This guide covers the three types of caching that Rails provides by default.</p></div>
<div class="paragraph"><p>This guide covers the three types of caching that Rails provides by default.</p></div>
</div></div>
<h2>Digging Deeper</h2>
<div class="sidebarblock">
@@ -303,20 +316,20 @@ understand how to use routing in your own Rails applications, start here.</p></d
<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/8">Lighthouse Ticket</a></td>
</tr></table>
</div>
<div class="para"><p>This is a rather comprehensive guide to doing both unit and functional tests
<div class="paragraph"><p>This is a rather comprehensive guide to doing both unit and functional tests
in Rails. It covers everything from &#8220;What is a test?&#8221; to the testing APIs.
Enjoy.</p></div>
</div></div>
<div class="sidebarblock">
<div class="sidebar-content">
<div class="sidebar-title"><a href="security.html">Securing Rails Applications</a></div>
<div class="para"><p>This guide describes common security problems in web applications and how to
<div class="paragraph"><p>This guide describes common security problems in web applications and how to
avoid them with Rails.</p></div>
</div></div>
<div class="sidebarblock">
<div class="sidebar-content">
<div class="sidebar-title"><a href="debugging_rails_applications.html">Debugging Rails Applications</a></div>
<div class="para"><p>This guide describes how to debug Rails applications. It covers the different
<div class="paragraph"><p>This guide describes how to debug Rails applications. It covers the different
ways of achieving this and how to understand what is happening "behind the scenes"
of your code.</p></div>
</div></div>
@@ -331,12 +344,12 @@ of your code.</p></div>
<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/4">Lighthouse Ticket</a></td>
</tr></table>
</div>
<div class="para"><p>This guide covers ways to analyze and optimize your running Rails code.</p></div>
<div class="paragraph"><p>This guide covers ways to analyze and optimize your running Rails code.</p></div>
</div></div>
<div class="sidebarblock">
<div class="sidebar-content">
<div class="sidebar-title"><a href="creating_plugins.html">The Basics of Creating Rails Plugins</a></div>
<div class="para"><p>This guide covers how to build a plugin to extend the functionality of Rails.</p></div>
<div class="paragraph"><p>This guide covers how to build a plugin to extend the functionality of Rails.</p></div>
</div></div>
<div class="sidebarblock">
<div class="sidebar-content">
@@ -349,10 +362,10 @@ of your code.</p></div>
<td class="content">still a basic draft</td>
</tr></table>
</div>
<div class="para"><p>This guide introduces you to the basic concepts and features of the Rails I18n API and shows you how to localize your application.</p></div>
<div class="paragraph"><p>This guide introduces you to the basic concepts and features of the Rails I18n API and shows you how to localize your application.</p></div>
</div></div>
<div class="para"><p>Authors who have contributed to complete guides are listed <a href="authors.html">here</a>.</p></div>
<div class="para"><p>This work is licensed under a <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-Noncommercial-Share Alike 3.0 License</a></p></div>
<div class="paragraph"><p>Authors who have contributed to complete guides are listed <a href="authors.html">here</a>.</p></div>
<div class="paragraph"><p>This work is licensed under a <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-Noncommercial-Share Alike 3.0 License</a></p></div>
</div>
</div>

File diff suppressed because it is too large Load Diff

View File

@@ -204,7 +204,7 @@ ul#navMain {
<li><a href="#_migrations_are_classes">Migrations are classes</a></li>
<li><a href="#_what_s_in_a_name">What's in a name</a></li>
<li><a href="#_what_8217_s_in_a_name">What&#8217;s in a name</a></li>
<li><a href="#_changing_migrations">Changing migrations</a></li>
@@ -279,10 +279,10 @@ ul#navMain {
<h1>Migrations</h1>
<div id="preamble">
<div class="sectionbody">
<div class="para"><p>Migrations are a convenient way for you to alter your database in a structured and organised manner. You could edit fragments of SQL by hand but you would then be responsible for telling other developers that they need to go and run it. You'd also have to keep track of which changes need to be run against the production machines next time you deploy. Active Record tracks which migrations have already been run so all you have to do is update your source and run <tt>rake db:migrate</tt>. Active Record will work out which migrations should be run. It will also update your db/schema.rb file to match the structure of your database.</p></div>
<div class="para"><p>Migrations also allow you to describe these transformations using Ruby. The great thing about this is that (like most of Active Record's functionality) it is database independent: you don't need to worry about the precise syntax of CREATE TABLE any more that you worry about variations on SELECT * (you can drop down to raw SQL for database specific features). For example you could use SQLite3 in development, but MySQL in production.</p></div>
<div class="para"><p>You'll learn all about migrations including:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>Migrations are a convenient way for you to alter your database in a structured and organised manner. You could edit fragments of SQL by hand but you would then be responsible for telling other developers that they need to go and run it. You&#8217;d also have to keep track of which changes need to be run against the production machines next time you deploy. Active Record tracks which migrations have already been run so all you have to do is update your source and run <tt>rake db:migrate</tt>. Active Record will work out which migrations should be run. It will also update your db/schema.rb file to match the structure of your database.</p></div>
<div class="paragraph"><p>Migrations also allow you to describe these transformations using Ruby. The great thing about this is that (like most of Active Record&#8217;s functionality) it is database independent: you don&#8217;t need to worry about the precise syntax of CREATE TABLE any more that you worry about variations on SELECT * (you can drop down to raw SQL for database specific features). For example you could use SQLite3 in development, but MySQL in production.</p></div>
<div class="paragraph"><p>You&#8217;ll learn all about migrations including:</p></div>
<div class="ulist"><ul>
<li>
<p>
The generators you can use to create them
@@ -308,7 +308,7 @@ How they relate to <tt>schema.rb</tt>
</div>
<h2 id="_anatomy_of_a_migration">1. Anatomy Of A Migration</h2>
<div class="sectionbody">
<div class="para"><p>Before I dive into the details of a migration, here are a few examples of the sorts of things you can do:</p></div>
<div class="paragraph"><p>Before I dive into the details of a migration, here are a few examples of the sorts of things you can do:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -327,10 +327,9 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
drop_table <span style="color: #990000">:</span>products
<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>This migration adds a table called <tt>products</tt> with a string column called <tt>name</tt> and a text column called <tt>description</tt>. A primary key column called <tt>id</tt> will also be added, however since this is the default we do not need to ask for this. The timestamp columns <tt>created_at</tt> and <tt>updated_at</tt> which Active Record populates automatically will also be added. Reversing this migration is as simple as dropping the table.</p></div>
<div class="para"><p>Migrations are not limited to changing the schema. You can also use them to fix bad data in the database or populate new fields:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This migration adds a table called <tt>products</tt> with a string column called <tt>name</tt> and a text column called <tt>description</tt>. A primary key column called <tt>id</tt> will also be added, however since this is the default we do not need to ask for this. The timestamp columns <tt>created_at</tt> and <tt>updated_at</tt> which Active Record populates automatically will also be added. Reversing this migration is as simple as dropping the table.</p></div>
<div class="paragraph"><p>Migrations are not limited to changing the schema. You can also use them to fix bad data in the database or populate new fields:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -347,9 +346,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
remove_column <span style="color: #990000">:</span>users<span style="color: #990000">,</span> <span style="color: #990000">:</span>receive_newsletter
<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>This migration adds an <tt>receive_newsletter</tt> column to the <tt>users</tt> table. We want it to default to <tt>false</tt> for new users, but existing users are considered
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This migration adds an <tt>receive_newsletter</tt> column to the <tt>users</tt> table. We want it to default to <tt>false</tt> for new users, but existing users are considered
to have already opted in, so we use the User model to set the flag to <tt>true</tt> for existing users.</p></div>
<div class="admonitionblock">
<table><tr>
@@ -360,9 +358,9 @@ to have already opted in, so we use the User model to set the flag to <tt>true</
</tr></table>
</div>
<h3 id="_migrations_are_classes">1.1. Migrations are classes</h3>
<div class="para"><p>A migration is a subclass of ActiveRecord::Migration that implements two class methods: <tt>up</tt> (perform the required transformations) and <tt>down</tt> (revert them).</p></div>
<div class="para"><p>Active Record provides methods that perform common data definition tasks in a database independent way (you'll read about them in detail later):</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>A migration is a subclass of ActiveRecord::Migration that implements two class methods: <tt>up</tt> (perform the required transformations) and <tt>down</tt> (revert them).</p></div>
<div class="paragraph"><p>Active Record provides methods that perform common data definition tasks in a database independent way (you&#8217;ll read about them in detail later):</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>create_table</tt>
@@ -409,24 +407,24 @@ to have already opted in, so we use the User model to set the flag to <tt>true</
</p>
</li>
</ul></div>
<div class="para"><p>If you need to perform tasks specific to your database (for example create a <a href="#foreign_key">foreign key</a> constraint) then the <tt>execute</tt> function allows you to execute arbitrary SQL. A migration is just a regular Ruby class so you're not limited to these functions. For example after adding a column you could
<div class="paragraph"><p>If you need to perform tasks specific to your database (for example create a <a href="#foreign_key">foreign key</a> constraint) then the <tt>execute</tt> function allows you to execute arbitrary SQL. A migration is just a regular Ruby class so you&#8217;re not limited to these functions. For example after adding a column you could
write code to set the value of that column for existing records (if necessary using your models).</p></div>
<div class="para"><p>On databases that support transactions with statements that change the schema (such as PostgreSQL), migrations are wrapped in a transaction. If the database does not support this (for example MySQL and SQLite) then when a migration fails the parts of it that succeeded will not be rolled back. You will have to unpick the changes that were made by hand.</p></div>
<h3 id="_what_s_in_a_name">1.2. What's in a name</h3>
<div class="para"><p>Migrations are stored in files in <tt>db/migrate</tt>, one for each migration class. The name of the file is of the form <tt>YYYYMMDDHHMMSS_create_products.rb</tt>, that is to say a UTC timestamp identifying the migration followed by an underscore followed by the name of the migration. The migration class' name must match (the camelcased version of) the latter part of the file name. For example <tt>20080906120000_create_products.rb</tt> should define CreateProducts and <tt>20080906120001_add_details_to_products.rb</tt> should define AddDetailsToProducts. If you do feel the need to change the file name then you MUST update the name of the class inside or Rails will complain about a missing class.</p></div>
<div class="para"><p>Internally Rails only uses the migration's number (the timestamp) to identify them. Prior to Rails 2.1 the migration number started at 1 and was incremented each time a migration was generated. With multiple developers it was easy for these to clash requiring you to rollback migrations and renumber them. With Rails 2.1 this is largely avoided by using the creation time of the migration to identify them. You can revert to the old numbering scheme by setting <tt>config.active_record.timestamped_migrations</tt> to <tt>false</tt> in <tt>environment.rb</tt>.</p></div>
<div class="para"><p>The combination of timestamps and recording which migrations have been run allows Rails to handle common situations that occur with multiple developers.</p></div>
<div class="para"><p>For example Alice adds migrations <tt>20080906120000</tt> and <tt>20080906123000</tt> and Bob adds <tt>20080906124500</tt> and runs it. Alice finishes her changes and checks in her migrations and Bob pulls down the latest changes. Rails knows that it has not run Alice's two migrations so <tt>rake db:migrate</tt> would run them (even though Bob's migration with a later timestamp has been run), and similarly migrating down would not run their down methods.</p></div>
<div class="para"><p>Of course this is no substitution for communication within the team, for example if Alice's migration removed a table that Bob's migration assumed the existence of then trouble will still occur.</p></div>
<div class="paragraph"><p>On databases that support transactions with statements that change the schema (such as PostgreSQL), migrations are wrapped in a transaction. If the database does not support this (for example MySQL and SQLite) then when a migration fails the parts of it that succeeded will not be rolled back. You will have to unpick the changes that were made by hand.</p></div>
<h3 id="_what_8217_s_in_a_name">1.2. What&#8217;s in a name</h3>
<div class="paragraph"><p>Migrations are stored in files in &#8216;db/migrate`, one for each migration class. The name of the file is of the form <tt>YYYYMMDDHHMMSS_create_products.rb</tt>, that is to say a UTC timestamp identifying the migration followed by an underscore followed by the name of the migration. The migration class&#8217; name must match (the camelcased version of) the latter part of the file name. For example <tt>20080906120000_create_products.rb</tt> should define CreateProducts and <tt>20080906120001_add_details_to_products.rb</tt> should define AddDetailsToProducts. If you do feel the need to change the file name then you MUST update the name of the class inside or Rails will complain about a missing class.</p></div>
<div class="paragraph"><p>Internally Rails only uses the migration&#8217;s number (the timestamp) to identify them. Prior to Rails 2.1 the migration number started at 1 and was incremented each time a migration was generated. With multiple developers it was easy for these to clash requiring you to rollback migrations and renumber them. With Rails 2.1 this is largely avoided by using the creation time of the migration to identify them. You can revert to the old numbering scheme by setting <tt>config.active_record.timestamped_migrations</tt> to <tt>false</tt> in <tt>environment.rb</tt>.</p></div>
<div class="paragraph"><p>The combination of timestamps and recording which migrations have been run allows Rails to handle common situations that occur with multiple developers.</p></div>
<div class="paragraph"><p>For example Alice adds migrations <tt>20080906120000</tt> and <tt>20080906123000</tt> and Bob adds <tt>20080906124500</tt> and runs it. Alice finishes her changes and checks in her migrations and Bob pulls down the latest changes. Rails knows that it has not run Alice&#8217;s two migrations so <tt>rake db:migrate</tt> would run them (even though Bob&#8217;s migration with a later timestamp has been run), and similarly migrating down would not run their down methods.</p></div>
<div class="paragraph"><p>Of course this is no substitution for communication within the team, for example if Alice&#8217;s migration removed a table that Bob&#8217;s migration assumed the existence of then trouble will still occur.</p></div>
<h3 id="_changing_migrations">1.3. Changing migrations</h3>
<div class="para"><p>Occasionally you will make a mistake while writing a migration. If you have already run the migration then you cannot just edit the migration and run the migration again: Rails thinks it has already run the migration and so will do nothing when you run <tt>rake db:migrate</tt>. You must rollback the migration (for example with <tt>rake db:rollback</tt>), edit your migration and then run <tt>rake db:migrate</tt> to run the corrected version.</p></div>
<div class="para"><p>In general editing existing migrations is not a good idea: you will be creating extra work for yourself and your co-workers and cause major headaches if the existing version of the migration has already been run on production machines. Instead you should write a new migration that performs the changes you require. Editing a freshly generated migration that has not yet been committed to source control (or more generally which has not been propagated beyond your development machine) is relatively harmless. Just use some common sense.</p></div>
<div class="paragraph"><p>Occasionally you will make a mistake while writing a migration. If you have already run the migration then you cannot just edit the migration and run the migration again: Rails thinks it has already run the migration and so will do nothing when you run <tt>rake db:migrate</tt>. You must rollback the migration (for example with <tt>rake db:rollback</tt>), edit your migration and then run <tt>rake db:migrate</tt> to run the corrected version.</p></div>
<div class="paragraph"><p>In general editing existing migrations is not a good idea: you will be creating extra work for yourself and your co-workers and cause major headaches if the existing version of the migration has already been run on production machines. Instead you should write a new migration that performs the changes you require. Editing a freshly generated migration that has not yet been committed to source control (or more generally which has not been propagated beyond your development machine) is relatively harmless. Just use some common sense.</p></div>
</div>
<h2 id="_creating_a_migration">2. Creating A Migration</h2>
<div class="sectionbody">
<h3 id="_creating_a_model">2.1. Creating a model</h3>
<div class="para"><p>The model and scaffold generators will create migrations appropriate for adding a new model. This migration will already contain instructions for creating the relevant table. If you tell Rails what columns you want then statements for adding those will also be created. For example, running</p></div>
<div class="para"><p><tt>ruby script/generate model Product name:string description:text</tt> will create a migration that looks like this</p></div>
<div class="paragraph"><p>The model and scaffold generators will create migrations appropriate for adding a new model. This migration will already contain instructions for creating the relevant table. If you tell Rails what columns you want then statements for adding those will also be created. For example, running</p></div>
<div class="paragraph"><p><tt>ruby script/generate model Product name:string description:text</tt> will create a migration that looks like this</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -445,14 +443,13 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
drop_table <span style="color: #990000">:</span>products
<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>You can append as many column name/type pairs as you want. By default <tt>t.timestamps</tt> (which creates the <tt>updated_at</tt> and <tt>created_at</tt> columns that
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>You can append as many column name/type pairs as you want. By default <tt>t.timestamps</tt> (which creates the <tt>updated_at</tt> and <tt>created_at</tt> columns that
are automatically populated by Active Record) will be added for you.</p></div>
<h3 id="_creating_a_standalone_migration">2.2. Creating a standalone migration</h3>
<div class="para"><p>If you are creating migrations for other purposes (for example to add a column to an existing table) then you can use the migration generator:</p></div>
<div class="para"><p><tt>ruby script/generate migration AddPartNumberToProducts</tt></p></div>
<div class="para"><p>This will create an empty but appropriately named migration:</p></div>
<div class="paragraph"><p>If you are creating migrations for other purposes (for example to add a column to an existing table) then you can use the migration generator:</p></div>
<div class="paragraph"><p><tt>ruby script/generate migration AddPartNumberToProducts</tt></p></div>
<div class="paragraph"><p>This will create an empty but appropriately named migration:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -464,12 +461,11 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
<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>If the migration name is of the form AddXXXToYYY or RemoveXXXFromY and is followed by a list of column names and types then a migration containing
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>If the migration name is of the form AddXXXToYYY or RemoveXXXFromY and is followed by a list of column names and types then a migration containing
the appropriate add and remove column statements will be created.</p></div>
<div class="para"><p><tt>ruby script/generate migration AddPartNumberToProducts part_number:string</tt></p></div>
<div class="para"><p>will generate</p></div>
<div class="paragraph"><p><tt>ruby script/generate migration AddPartNumberToProducts part_number:string</tt></p></div>
<div class="paragraph"><p>will generate</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -483,11 +479,10 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
remove_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number
<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>Similarly,</p></div>
<div class="para"><p><tt>ruby script/generate migration RemovePartNumberFromProducts part_number:string</tt></p></div>
<div class="para"><p>generates</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Similarly,</p></div>
<div class="paragraph"><p><tt>ruby script/generate migration RemovePartNumberFromProducts part_number:string</tt></p></div>
<div class="paragraph"><p>generates</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -501,11 +496,10 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
add_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number<span style="color: #990000">,</span> <span style="color: #990000">:</span>string
<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>You are not limited to one magically generated column, for example</p></div>
<div class="para"><p><tt>ruby script/generate migration AddDetailsToProducts part_number:string price:decimal</tt></p></div>
<div class="para"><p>generates</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>You are not limited to one magically generated column, for example</p></div>
<div class="paragraph"><p><tt>ruby script/generate migration AddDetailsToProducts part_number:string price:decimal</tt></p></div>
<div class="paragraph"><p>generates</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -521,15 +515,14 @@ http://www.gnu.org/software/src-highlite -->
remove_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>price
remove_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number
<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>As always, what has been generated for you is just a starting point. You can add or remove from it as you see fit.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>As always, what has been generated for you is just a starting point. You can add or remove from it as you see fit.</p></div>
</div>
<h2 id="_writing_a_migration">3. Writing a Migration</h2>
<div class="sectionbody">
<div class="para"><p>Once you have created your migration using one of the generators it's time to get to work!</p></div>
<div class="paragraph"><p>Once you have created your migration using one of the generators it&#8217;s time to get to work!</p></div>
<h3 id="_creating_a_table">3.1. Creating a table</h3>
<div class="para"><p><tt>create_table</tt> will be one of your workhorses. A typical use would be</p></div>
<div class="paragraph"><p><tt>create_table</tt> will be one of your workhorses. A typical use would be</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -537,10 +530,9 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>which creates a <tt>products</tt> table with a column called <tt>name</tt> (and as discussed below, an implicit <tt>id</tt> column).</p></div>
<div class="para"><p>The object yielded to the block allows you create columns on the table. There are two ways of doing this. The first looks like</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>which creates a <tt>products</tt> table with a column called <tt>name</tt> (and as discussed below, an implicit <tt>id</tt> column).</p></div>
<div class="paragraph"><p>The object yielded to the block allows you create columns on the table. There are two ways of doing this. The first looks like</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -548,9 +540,8 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
t<span style="color: #990000">.</span>column <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>string<span style="color: #990000">,</span> <span style="color: #990000">:</span>null <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>the second form, the so called "sexy" migrations, drops the somewhat redundant column method. Instead, the <tt>string</tt>, <tt>integer</tt> etc. methods create a column of that type. Subsequent parameters are identical.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>the second form, the so called "sexy" migrations, drops the somewhat redundant column method. Instead, the <tt>string</tt>, <tt>integer</tt> etc. methods create a column of that type. Subsequent parameters are identical.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -558,9 +549,8 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>null <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>By default <tt>create_table</tt> will create a primary key called <tt>id</tt>. You can change the name of the primary key with the <tt>:primary_key</tt> option (don't forget to update the corresponding model) or if you don't want a primary key at all (for example for a HABTM join table) you can pass <tt>:id &#8658; false</tt>. If you need to pass database specific options you can place an sql fragment in the <tt>:options</tt> option. For example</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>By default <tt>create_table</tt> will create a primary key called <tt>id</tt>. You can change the name of the primary key with the <tt>:primary_key</tt> option (don&#8217;t forget to update the corresponding model) or if you don&#8217;t want a primary key at all (for example for a HABTM join table) you can pass <tt>:id =&gt; false</tt>. If you need to pass database specific options you can place an sql fragment in the <tt>:options</tt> option. For example</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -568,11 +558,10 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>create_table <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>options <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"ENGINE=BLACKHOLE"</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>null <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>Will append <tt>ENGINE=BLACKHOLE</tt> to the sql used to create the table (when using MySQL the default is "ENGINE=InnoDB").</p></div>
<div class="para"><p>The types Active Record supports are <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>, <tt>:integer</tt>, <tt>:float</tt>, <tt>:decimal</tt>, <tt>:datetime</tt>, <tt>:timestamp</tt>, <tt>:time</tt>, <tt>:date</tt>, <tt>:binary</tt>, <tt>:boolean</tt>.</p></div>
<div class="para"><p>These will be mapped onto an appropriate underlying database type, for example with MySQL <tt>:string</tt> is mapped to <tt>VARCHAR(255)</tt>. You can create columns of
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Will append <tt>ENGINE=BLACKHOLE</tt> to the sql used to create the table (when using MySQL the default is "ENGINE=InnoDB").</p></div>
<div class="paragraph"><p>The types Active Record supports are <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>, <tt>:integer</tt>, <tt>:float</tt>, <tt>:decimal</tt>, <tt>:datetime</tt>, <tt>:timestamp</tt>, <tt>:time</tt>, <tt>:date</tt>, <tt>:binary</tt>, <tt>:boolean</tt>.</p></div>
<div class="paragraph"><p>These will be mapped onto an appropriate underlying database type, for example with MySQL <tt>:string</tt> is mapped to <tt>VARCHAR(255)</tt>. You can create columns of
types not supported by Active Record when using the non sexy syntax, for example</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
@@ -581,11 +570,10 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
t<span style="color: #990000">.</span>column <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #FF0000">'polygon'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>null <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">false</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>This may however hinder portability to other databases.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>This may however hinder portability to other databases.</p></div>
<h3 id="_changing_tables">3.2. Changing tables</h3>
<div class="para"><p><tt>create_table</tt>'s close cousin is <tt>change_table</tt>. Used for changing existing tables, it is used in a similar fashion to <tt>create_table</tt> but the object yielded to the block knows more tricks. For example</p></div>
<div class="paragraph"><p><tt>create_table</tt>'s close cousin is <tt>change_table</tt>. Used for changing existing tables, it is used in a similar fashion to <tt>create_table</tt> but the object yielded to the block knows more tricks. For example</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -596,9 +584,8 @@ http://www.gnu.org/software/src-highlite -->
t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>part_number
t<span style="color: #990000">.</span>index <span style="color: #990000">:</span>part_number
t<span style="color: #990000">.</span>rename <span style="color: #990000">:</span>upccode<span style="color: #990000">,</span> <span style="color: #990000">:</span>upc_code
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>removes the <tt>description</tt> column, creates a <tt>part_number</tt> column and adds an index on it. Finally it renames the <tt>upccode</tt> column. This is the same as doing</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>removes the <tt>description</tt> column, creates a <tt>part_number</tt> column and adds an index on it. Finally it renames the <tt>upccode</tt> column. This is the same as doing</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -608,11 +595,10 @@ http://www.gnu.org/software/src-highlite -->
remove_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>name
add_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number<span style="color: #990000">,</span> <span style="color: #990000">:</span>string
add_index <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>part_number
rename_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>upccode<span style="color: #990000">,</span> <span style="color: #990000">:</span>upc_code
</tt></pre></div></div>
<div class="para"><p>You don't have to keep repeating the table name and it groups all the statements related to modifying one particular table. The individual transformation names are also shorter, for example <tt>remove_column</tt> becomes just <tt>remove</tt> and <tt>add_index</tt> becomes just <tt>index</tt>.</p></div>
rename_column <span style="color: #990000">:</span>products<span style="color: #990000">,</span> <span style="color: #990000">:</span>upccode<span style="color: #990000">,</span> <span style="color: #990000">:</span>upc_code</tt></pre></div></div>
<div class="paragraph"><p>You don&#8217;t have to keep repeating the table name and it groups all the statements related to modifying one particular table. The individual transformation names are also shorter, for example <tt>remove_column</tt> becomes just <tt>remove</tt> and <tt>add_index</tt> becomes just <tt>index</tt>.</p></div>
<h3 id="_special_helpers">3.3. Special helpers</h3>
<div class="para"><p>Active Record provides some shortcuts for common functionality. It is for example very common to add both the <tt>created_at</tt> and <tt>updated_at</tt> columns and so there is a method that does exactly that:</p></div>
<div class="paragraph"><p>Active Record provides some shortcuts for common functionality. It is for example very common to add both the <tt>created_at</tt> and <tt>updated_at</tt> columns and so there is a method that does exactly that:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -620,9 +606,8 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
t<span style="color: #990000">.</span>timestamps
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>will create a new products table with those two columns whereas</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>will create a new products table with those two columns whereas</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -630,10 +615,9 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>change_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
t<span style="color: #990000">.</span>timestamps
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>adds those columns to an existing table.</p></div>
<div class="para"><p>The other helper is called <tt>references</tt> (also available as <tt>belongs_to</tt>). In its simplest form it just adds some readability</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>adds those columns to an existing table.</p></div>
<div class="paragraph"><p>The other helper is called <tt>references</tt> (also available as <tt>belongs_to</tt>). In its simplest form it just adds some readability</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -641,9 +625,8 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
t<span style="color: #990000">.</span>references <span style="color: #990000">:</span>category
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>will create a <tt>category_id</tt> column of the appropriate type. Note that you pass the model name, not the column name. Active Record adds the <tt>_id</tt> for you. If you have polymorphic belongs_to associations then <tt>references</tt> will add both of the columns required:</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>will create a <tt>category_id</tt> column of the appropriate type. Note that you pass the model name, not the column name. Active Record adds the <tt>_id</tt> for you. If you have polymorphic belongs_to associations then <tt>references</tt> will add both of the columns required:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -651,9 +634,8 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>create_table <span style="color: #990000">:</span>products <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>t<span style="color: #990000">|</span>
t<span style="color: #990000">.</span>references <span style="color: #990000">:</span>attachment<span style="color: #990000">,</span> <span style="color: #990000">:</span>polymorphic <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span><span style="color: #990000">:</span>default <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Photo'</span><span style="color: #FF0000">}</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>will add an <tt>attachment_id</tt> column and a string <tt>attachment_type</tt> column with a default value of <em>Photo</em>.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>will add an <tt>attachment_id</tt> column and a string <tt>attachment_type</tt> column with a default value of <em>Photo</em>.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -662,10 +644,10 @@ http://www.gnu.org/software/src-highlite -->
<td class="content">The <tt>references</tt> helper does not actually create foreign key constraints for you. You will need to use <tt>execute</tt> for that or a plugin that adds <a href="#foreign_key">foreign key support</a>.</td>
</tr></table>
</div>
<div class="para"><p>If the helpers provided by Active Record aren't enough you can use the <tt>execute</tt> function to execute arbitrary SQL.</p></div>
<div class="para"><p>For more details and examples of individual methods check the API documentation, in particular the documentation for <a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html">ActiveRecord::ConnectionAdapters::SchemaStatements</a> (which provides the methods available in the <tt>up</tt> and <tt>down</tt> methods), <a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html">ActiveRecord::ConnectionAdapters::TableDefinition</a> (which provides the methods available on the object yielded by <tt>create_table</tt>) and <a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/Table.html">ActiveRecord::ConnectionAdapters::Table</a> (which provides the methods available on the object yielded by <tt>change_table</tt>).</p></div>
<div class="paragraph"><p>If the helpers provided by Active Record aren&#8217;t enough you can use the <tt>execute</tt> function to execute arbitrary SQL.</p></div>
<div class="paragraph"><p>For more details and examples of individual methods check the API documentation, in particular the documentation for <a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html">ActiveRecord::ConnectionAdapters::SchemaStatements</a> (which provides the methods available in the <tt>up</tt> and <tt>down</tt> methods), <a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html">ActiveRecord::ConnectionAdapters::TableDefinition</a> (which provides the methods available on the object yielded by <tt>create_table</tt>) and <a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/Table.html">ActiveRecord::ConnectionAdapters::Table</a> (which provides the methods available on the object yielded by <tt>change_table</tt>).</p></div>
<h3 id="_writing_your_down_method">3.4. Writing your down method</h3>
<div class="para"><p>The <tt>down</tt> method of your migration should revert the transformations done by the <tt>up</tt> method. In other words the database should be unchanged if you do an <tt>up</tt> followed by a <tt>down</tt>. For example if you create a table in the up you should drop it in the <tt>down</tt> method. It is wise to do things in precisely the reverse order to in the <tt>up</tt> method. For example</p></div>
<div class="paragraph"><p>The <tt>down</tt> method of your migration should revert the transformations done by the <tt>up</tt> method. In other words the database should be unchanged if you do an <tt>up</tt> followed by a <tt>down</tt>. For example if you create a table in the up you should drop it in the <tt>down</tt> method. It is wise to do things in precisely the reverse order to in the <tt>up</tt> method. For example</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -691,41 +673,40 @@ http://www.gnu.org/software/src-highlite -->
execute <span style="color: #FF0000">"ALTER TABLE products DROP FOREIGN KEY fk_products_categories"</span>
drop_table <span style="color: #990000">:</span>products
<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>Sometimes your migration will do something which is just plain irreversible, for example it might destroy some data. In cases like those when you can't reverse the migration you can raise IrreversibleMigration from your <tt>down</tt> method. If someone tries to revert your migration an error message will be
displayed saying that it can't be done.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Sometimes your migration will do something which is just plain irreversible, for example it might destroy some data. In cases like those when you can&#8217;t reverse the migration you can raise IrreversibleMigration from your <tt>down</tt> method. If someone tries to revert your migration an error message will be
displayed saying that it can&#8217;t be done.</p></div>
</div>
<h2 id="_running_migrations">4. Running Migrations</h2>
<div class="sectionbody">
<div class="para"><p>Rails provides a set of rake tasks to work with migrations which boils down to running certain sets of migrations. The very first migration related rake task you use will probably be <tt>db:migrate</tt>. In its most basic form it just runs the <tt>up</tt> method for all the migrations that have not yet been run. If there are no such migrations it exits.</p></div>
<div class="para"><p>Note that running the <tt>db:migrate</tt> also invokes the <tt>db:schema:dump</tt> task, which will update your db/schema.rb file to match the structure of your database.</p></div>
<div class="para"><p>If you specify a target version, Active Record will run the required migrations (up or down) until it has reached the specified version. The
version is the numerical prefix on the migration's filename. For example to migrate to version 20080906120000 run</p></div>
<div class="paragraph"><p>Rails provides a set of rake tasks to work with migrations which boils down to running certain sets of migrations. The very first migration related rake task you use will probably be <tt>db:migrate</tt>. In its most basic form it just runs the <tt>up</tt> method for all the migrations that have not yet been run. If there are no such migrations it exits.</p></div>
<div class="paragraph"><p>Note that running the <tt>db:migrate</tt> also invokes the <tt>db:schema:dump</tt> task, which will update your db/schema.rb file to match the structure of your database.</p></div>
<div class="paragraph"><p>If you specify a target version, Active Record will run the required migrations (up or down) until it has reached the specified version. The
version is the numerical prefix on the migration&#8217;s filename. For example to migrate to version 20080906120000 run</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>rake db:migrate VERSION=20080906120000</tt></pre>
</div></div>
<div class="para"><p>If this is greater than the current version (i.e. it is migrating upwards) this will run the <tt>up</tt> method on all migrations up to and including 20080906120000, if migrating downwards this will run the <tt>down</tt> method on all the migrations down to, but not including, 20080906120000.</p></div>
<div class="paragraph"><p>If this is greater than the current version (i.e. it is migrating upwards) this will run the <tt>up</tt> method on all migrations up to and including 20080906120000, if migrating downwards this will run the <tt>down</tt> method on all the migrations down to, but not including, 20080906120000.</p></div>
<h3 id="_rolling_back">4.1. Rolling back</h3>
<div class="para"><p>A common task is to rollback the last migration, for example if you made a mistake in it and wish to correct it. Rather than tracking down the version number associated with the previous migration you can run</p></div>
<div class="paragraph"><p>A common task is to rollback the last migration, for example if you made a mistake in it and wish to correct it. Rather than tracking down the version number associated with the previous migration you can run</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>rake db:rollback</tt></pre>
</div></div>
<div class="para"><p>This will run the <tt>down</tt> method from the latest migration. If you need to undo several migrations you can provide a <tt>STEP</tt> parameter:</p></div>
<div class="paragraph"><p>This will run the <tt>down</tt> method from the latest migration. If you need to undo several migrations you can provide a <tt>STEP</tt> parameter:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>rake db:rollback STEP=3</tt></pre>
</div></div>
<div class="para"><p>will run the <tt>down</tt> method from the last 3 migrations.</p></div>
<div class="para"><p>The <tt>db:migrate:redo</tt> task is a shortcut for doing a rollback and then migrating back up again. As with the <tt>db:rollback</tt> task you can use the <tt>STEP</tt> parameter if you need to go more than one version back, for example</p></div>
<div class="paragraph"><p>will run the <tt>down</tt> method from the last 3 migrations.</p></div>
<div class="paragraph"><p>The <tt>db:migrate:redo</tt> task is a shortcut for doing a rollback and then migrating back up again. As with the <tt>db:rollback</tt> task you can use the <tt>STEP</tt> parameter if you need to go more than one version back, for example</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>rake db:migrate:redo STEP=3</tt></pre>
</div></div>
<div class="para"><p>Neither of these Rake tasks do anything you could not do with <tt>db:migrate</tt>, they are simply more convenient since you do not need to explicitly specify the version to migrate to.</p></div>
<div class="para"><p>Lastly, the <tt>db:reset</tt> task will drop the database, recreate it and load the current schema into it.</p></div>
<div class="paragraph"><p>Neither of these Rake tasks do anything you could not do with <tt>db:migrate</tt>, they are simply more convenient since you do not need to explicitly specify the version to migrate to.</p></div>
<div class="paragraph"><p>Lastly, the <tt>db:reset</tt> task will drop the database, recreate it and load the current schema into it.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -735,14 +716,14 @@ version is the numerical prefix on the migration's filename. For example to migr
</tr></table>
</div>
<h3 id="_being_specific">4.2. Being Specific</h3>
<div class="para"><p>If you need to run a specific migration up or down the <tt>db:migrate:up</tt> and <tt>db:migrate:down</tt> tasks will do that. Just specify the appropriate version and the corresponding migration will have its <tt>up</tt> or <tt>down</tt> method invoked, for example</p></div>
<div class="paragraph"><p>If you need to run a specific migration up or down the <tt>db:migrate:up</tt> and <tt>db:migrate:down</tt> tasks will do that. Just specify the appropriate version and the corresponding migration will have its <tt>up</tt> or <tt>down</tt> method invoked, for example</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>rake db:migrate:up VERSION=20080906120000</tt></pre>
</div></div>
<div class="para"><p>will run the <tt>up</tt> method from the 20080906120000 migration. These tasks check whether the migration has already run, so for example <tt>db:migrate:up VERSION=20080906120000</tt> will do nothing if Active Record believes that 20080906120000 has already been run.</p></div>
<div class="paragraph"><p>will run the <tt>up</tt> method from the 20080906120000 migration. These tasks check whether the migration has already run, so for example <tt>db:migrate:up VERSION=20080906120000</tt> will do nothing if Active Record believes that 20080906120000 has already been run.</p></div>
<h3 id="_being_talkative">4.3. Being talkative</h3>
<div class="para"><p>By default migrations tell you exactly what they're doing and how long it took.
<div class="paragraph"><p>By default migrations tell you exactly what they&#8217;re doing and how long it took.
A migration creating a table and adding an index might produce output like this</p></div>
<div class="listingblock">
<div class="content">
@@ -753,8 +734,8 @@ A migration creating a table and adding an index might produce output like this<
-&gt; 0.0026s
== 20080906170109 CreateProducts: migrated (0.0059s) ==========================</tt></pre>
</div></div>
<div class="para"><p>Several methods are provided that allow you to control all this:</p></div>
<div class="ilist"><ul>
<div class="paragraph"><p>Several methods are provided that allow you to control all this:</p></div>
<div class="ulist"><ul>
<li>
<p>
<tt>suppress_messages</tt> suppresses any output generated by its block
@@ -771,7 +752,7 @@ A migration creating a table and adding an index might produce output like this<
</p>
</li>
</ul></div>
<div class="para"><p>For example, this migration</p></div>
<div class="paragraph"><p>For example, this migration</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -798,9 +779,8 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
drop_table <span style="color: #990000">:</span>products
<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>generates the following output</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>generates the following output</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>== 20080906170109 CreateProducts: migrating ===================================
@@ -811,13 +791,13 @@ http://www.gnu.org/software/src-highlite -->
-&gt; 250 rows
== 20080906170109 CreateProducts: migrated (10.0097s) =========================</tt></pre>
</div></div>
<div class="para"><p>If you just want Active Record to shut up then running <tt>rake db:migrate VERBOSE=false</tt> will suppress any output.</p></div>
<div class="paragraph"><p>If you just want Active Record to shut up then running <tt>rake db:migrate VERBOSE=false</tt> will suppress any output.</p></div>
</div>
<h2 id="models">5. Using Models In Your Migrations</h2>
<div class="sectionbody">
<div class="para"><p>When creating or updating data in a migration it is often tempting to use one of your models. After all they exist to provide easy access to the underlying data. This can be done but some caution should be observed.</p></div>
<div class="para"><p>Consider for example a migration that uses the Product model to update a row in the corresponding table. Alice later updates the Product model, adding a new column and a validation on it. Bob comes back from holiday, updates the source and runs outstanding migrations with <tt>rake db:migrate</tt>, including the one that used the Product model. When the migration runs the source is up to date and so the Product model has the validation added by Alice. The database however is still old and so does not have that column and an error ensues because that validation is on a column that does not yet exist.</p></div>
<div class="para"><p>Frequently I just want to update rows in the database without writing out the SQL by hand: I'm not using anything specific to the model. One pattern for this is to define a copy of the model inside the migration itself, for example:</p></div>
<div class="paragraph"><p>When creating or updating data in a migration it is often tempting to use one of your models. After all they exist to provide easy access to the underlying data. This can be done but some caution should be observed.</p></div>
<div class="paragraph"><p>Consider for example a migration that uses the Product model to update a row in the corresponding table. Alice later updates the Product model, adding a new column and a validation on it. Bob comes back from holiday, updates the source and runs outstanding migrations with <tt>rake db:migrate</tt>, including the one that used the Product model. When the migration runs the source is up to date and so the Product model has the validation added by Alice. The database however is still old and so does not have that column and an error ensues because that validation is on a column that does not yet exist.</p></div>
<div class="paragraph"><p>Frequently I just want to update rows in the database without writing out the SQL by hand: I&#8217;m not using anything specific to the model. One pattern for this is to define a copy of the model inside the migration itself, for example:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -834,11 +814,10 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
<span style="color: #990000">...</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>The migration has its own minimal copy of the Product model and no longer cares about the Product model defined in the application.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>The migration has its own minimal copy of the Product model and no longer cares about the Product model defined in the application.</p></div>
<h3 id="_dealing_with_changing_models">5.1. Dealing with changing models</h3>
<div class="para"><p>For performance reasons information about the columns a model has is cached. For example if you add a column to a table and then try and use the corresponding model to insert a new row it may try and use the old column information. You can force Active Record to re-read the column information with the <tt>reset_column_information</tt> method, for example</p></div>
<div class="paragraph"><p>For performance reasons information about the columns a model has is cached. For example if you add a column to a table and then try and use the corresponding model to insert a new row it may try and use the old column information. You can force Active Record to re-read the column information with the <tt>reset_column_information</tt> method, for example</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -857,19 +836,18 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>down
<span style="color: #990000">...</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>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
</div>
<h2 id="_schema_dumping_and_you">6. Schema dumping and you</h2>
<div class="sectionbody">
<h3 id="schema">6.1. What are schema files for?</h3>
<div class="para"><p>Migrations, mighty as they may be, are not the authoritative source for your database schema. That role falls to either <tt>schema.rb</tt> or an SQL file which Active Record generates by examining the database. They are not designed to be edited, they just represent the current state of the database.</p></div>
<div class="para"><p>There is no need (and it is error prone) to deploy a new instance of an app by replaying the entire migration history. It is much simpler and faster to just load into the database a description of the current schema.</p></div>
<div class="para"><p>For example, this is how the test database is created: the current development database is dumped (either to <tt>schema.rb</tt> or <tt>development.sql</tt>) and then loaded into the test database.</p></div>
<div class="para"><p>Schema files are also useful if you want a quick look at what attributes an Active Record object has. This information is not in the model's code and is frequently spread across several migrations but is all summed up in the schema file. The <a href="http://agilewebdevelopment.com/plugins/annotate_models">annotate_models</a> plugin, which automatically adds (and updates) comments at the top of each model summarising the schema, may also be of interest.</p></div>
<div class="paragraph"><p>Migrations, mighty as they may be, are not the authoritative source for your database schema. That role falls to either <tt>schema.rb</tt> or an SQL file which Active Record generates by examining the database. They are not designed to be edited, they just represent the current state of the database.</p></div>
<div class="paragraph"><p>There is no need (and it is error prone) to deploy a new instance of an app by replaying the entire migration history. It is much simpler and faster to just load into the database a description of the current schema.</p></div>
<div class="paragraph"><p>For example, this is how the test database is created: the current development database is dumped (either to <tt>schema.rb</tt> or <tt>development.sql</tt>) and then loaded into the test database.</p></div>
<div class="paragraph"><p>Schema files are also useful if you want a quick look at what attributes an Active Record object has. This information is not in the model&#8217;s code and is frequently spread across several migrations but is all summed up in the schema file. The <a href="http://agilewebdevelopment.com/plugins/annotate_models">annotate_models</a> plugin, which automatically adds (and updates) comments at the top of each model summarising the schema, may also be of interest.</p></div>
<h3 id="_types_of_schema_dumps">6.2. Types of schema dumps</h3>
<div class="para"><p>There are two ways to dump the schema. This is set in <tt>config/environment.rb</tt> by the <tt>config.active_record.schema_format</tt> setting, which may be either <tt>:sql</tt> or <tt>:ruby</tt>.</p></div>
<div class="para"><p>If <tt>:ruby</tt> is selected then the schema is stored in <tt>db/schema.rb</tt>. If you look at this file you'll find that it looks an awful lot like one very big migration:</p></div>
<div class="paragraph"><p>There are two ways to dump the schema. This is set in <tt>config/environment.rb</tt> by the <tt>config.active_record.schema_format</tt> setting, which may be either <tt>:sql</tt> or <tt>:ruby</tt>.</p></div>
<div class="paragraph"><p>If <tt>:ruby</tt> is selected then the schema is stored in <tt>db/schema.rb</tt>. If you look at this file you&#8217;ll find that it looks an awful lot like one very big migration:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -889,25 +867,24 @@ http://www.gnu.org/software/src-highlite -->
t<span style="color: #990000">.</span>datetime <span style="color: #FF0000">"updated_at"</span>
t<span style="color: #990000">.</span>string <span style="color: #FF0000">"part_number"</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>In many ways this is exactly what it is. This file is created by inspecting the database and expressing its structure using <tt>create_table</tt>, <tt>add_index</tt> and so on. Because this is database independent it could be loaded into any database that Active Record supports. This could be very useful if you were to distribute an application that is able to run against multiple databases.</p></div>
<div class="para"><p>There is however a trade-off: <tt>schema.rb</tt> cannot express database specific items such as foreign key constraints, triggers or stored procedures. While in a migration you can execute custom SQL statements, the schema dumper cannot reconstitute those statements from the database. If you are using features like this then you should set the schema format to <tt>:sql</tt>.</p></div>
<div class="para"><p>Instead of using Active Record's schema dumper the database's structure will be dumped using a tool specific to that database (via the <tt>db:structure:dump</tt> Rake task) into <tt>db/#{RAILS_ENV}_structure.sql</tt>. For example for PostgreSQL the <tt>pg_dump</tt> utility is used and for MySQL this file will contain the output of SHOW CREATE TABLE for the various tables. Loading this schema is simply a question of executing the SQL statements contained inside.</p></div>
<div class="para"><p>By definition this will be a perfect copy of the database's structure but this will usually prevent loading the schema into a database other than the one used to create it.</p></div>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>In many ways this is exactly what it is. This file is created by inspecting the database and expressing its structure using <tt>create_table</tt>, <tt>add_index</tt> and so on. Because this is database independent it could be loaded into any database that Active Record supports. This could be very useful if you were to distribute an application that is able to run against multiple databases.</p></div>
<div class="paragraph"><p>There is however a trade-off: <tt>schema.rb</tt> cannot express database specific items such as foreign key constraints, triggers or stored procedures. While in a migration you can execute custom SQL statements, the schema dumper cannot reconstitute those statements from the database. If you are using features like this then you should set the schema format to <tt>:sql</tt>.</p></div>
<div class="paragraph"><p>Instead of using Active Record&#8217;s schema dumper the database&#8217;s structure will be dumped using a tool specific to that database (via the <tt>db:structure:dump</tt> Rake task) into <tt>db/#{RAILS_ENV}_structure.sql</tt>. For example for PostgreSQL the <tt>pg_dump</tt> utility is used and for MySQL this file will contain the output of SHOW CREATE TABLE for the various tables. Loading this schema is simply a question of executing the SQL statements contained inside.</p></div>
<div class="paragraph"><p>By definition this will be a perfect copy of the database&#8217;s structure but this will usually prevent loading the schema into a database other than the one used to create it.</p></div>
<h3 id="_schema_dumps_and_source_control">6.3. Schema dumps and source control</h3>
<div class="para"><p>Because they are the authoritative source for your database schema, it is strongly recommended that you check them into source control.</p></div>
<div class="paragraph"><p>Because they are the authoritative source for your database schema, it is strongly recommended that you check them into source control.</p></div>
</div>
<h2 id="foreign_key">7. Active Record and Referential Integrity</h2>
<div class="sectionbody">
<div class="para"><p>The Active Record way is that intelligence belongs in your models, not in the database. As such, features such as triggers or foreign key constraints, which push some of that intelligence back into the database are not heavily used.</p></div>
<div class="para"><p>Validations such as <tt>validates_uniqueness_of</tt> are one way in which models can enforce data integrity. The <tt>:dependent</tt> option on associations allows models to automatically destroy child objects when the parent is destroyed. Like anything which operates at the application level these cannot guarantee referential integrity and so some people augment them with foreign key constraints.</p></div>
<div class="para"><p>Although Active Record does not provide any tools for working directly with such features, the <tt>execute</tt> method can be used to execute arbitrary SQL. There are also a number of plugins such as <a href="http://agilewebdevelopment.com/plugins/search?search=redhillonrails">redhillonrails</a> which add foreign key support to Active Record (including support for dumping foreign keys in <tt>schema.rb</tt>).</p></div>
<div class="paragraph"><p>The Active Record way is that intelligence belongs in your models, not in the database. As such, features such as triggers or foreign key constraints, which push some of that intelligence back into the database are not heavily used.</p></div>
<div class="paragraph"><p>Validations such as <tt>validates_uniqueness_of</tt> are one way in which models can enforce data integrity. The <tt>:dependent</tt> option on associations allows models to automatically destroy child objects when the parent is destroyed. Like anything which operates at the application level these cannot guarantee referential integrity and so some people augment them with foreign key constraints.</p></div>
<div class="paragraph"><p>Although Active Record does not provide any tools for working directly with such features, the <tt>execute</tt> method can be used to execute arbitrary SQL. There are also a number of plugins such as <a href="http://agilewebdevelopment.com/plugins/search?search=redhillonrails">redhillonrails</a> which add foreign key support to Active Record (including support for dumping foreign keys in <tt>schema.rb</tt>).</p></div>
</div>
<h2 id="_changelog">8. Changelog</h2>
<div class="sectionbody">
<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/6">Lighthouse ticket</a></p></div>
<div class="ilist"><ul>
<div class="paragraph"><p><a href="http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/6">Lighthouse ticket</a></p></div>
<div class="ulist"><ul>
<li>
<p>
September 14, 2008: initial version by <a href="../authors.html#fcheung">Frederick Cheung</a>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff