aboutsummaryrefslogtreecommitdiffstats
path: root/railties/doc/guides
diff options
context:
space:
mode:
authorAhmed El-Daly <aeldaly@developergurus.com>2009-01-29 23:04:49 -0500
committerAhmed El-Daly <aeldaly@developergurus.com>2009-01-29 23:04:49 -0500
commit43d63298f7693a437b454b4b8ee84946af350572 (patch)
tree55166f7c3118061a1fd0df2cb3cf6ea6e31647b9 /railties/doc/guides
parent6623e4f92a69c2aa0a12957db430b00690d50d19 (diff)
parent24b688d31d34dc7582c8e2ac4347d0c36e3c5e10 (diff)
downloadrails-43d63298f7693a437b454b4b8ee84946af350572.tar.gz
rails-43d63298f7693a437b454b4b8ee84946af350572.tar.bz2
rails-43d63298f7693a437b454b4b8ee84946af350572.zip
Merge branch 'master' of git@github.com:lifo/docrails
Diffstat (limited to 'railties/doc/guides')
-rw-r--r--railties/doc/guides/html/2_3_release_notes.html892
-rw-r--r--railties/doc/guides/html/action_mailer_basics.html37
-rw-r--r--railties/doc/guides/html/actioncontroller_basics.html52
-rw-r--r--railties/doc/guides/html/active_record_basics.html335
-rw-r--r--railties/doc/guides/html/creating_plugins.html32
-rw-r--r--railties/doc/guides/html/form_helpers.html243
-rw-r--r--railties/doc/guides/html/i18n.html337
-rw-r--r--railties/doc/guides/html/index.html10
-rw-r--r--railties/doc/guides/source/2_3_release_notes.txt399
-rw-r--r--railties/doc/guides/source/action_mailer_basics.txt6
-rw-r--r--railties/doc/guides/source/actioncontroller_basics/http_auth.txt39
-rw-r--r--railties/doc/guides/source/active_record_basics.txt202
-rw-r--r--railties/doc/guides/source/creating_plugins/creating_plugins/lib/main.rb4
-rw-r--r--railties/doc/guides/source/creating_plugins/generator_commands.txt2
-rw-r--r--railties/doc/guides/source/creating_plugins/migrations.txt23
-rw-r--r--railties/doc/guides/source/creating_plugins/models.txt2
-rw-r--r--railties/doc/guides/source/creating_plugins/tasks.txt4
-rw-r--r--railties/doc/guides/source/creating_plugins/test_setup.txt3
-rw-r--r--railties/doc/guides/source/form_helpers.txt222
-rw-r--r--railties/doc/guides/source/i18n.txt273
-rw-r--r--railties/doc/guides/source/index.txt16
21 files changed, 2452 insertions, 681 deletions
diff --git a/railties/doc/guides/html/2_3_release_notes.html b/railties/doc/guides/html/2_3_release_notes.html
new file mode 100644
index 0000000000..07e825ca99
--- /dev/null
+++ b/railties/doc/guides/html/2_3_release_notes.html
@@ -0,0 +1,892 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<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 2.3 Release Notes</title>
+ <!--[if lt IE 8]>
+ <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script>
+ <![endif]-->
+ <link href="stylesheets/base.css" media="screen" rel="Stylesheet" type="text/css" />
+ <link href="stylesheets/forms.css" media="screen" rel="Stylesheet" type="text/css" />
+ <link href="stylesheets/more.css" media="screen" rel="Stylesheet" type="text/css" />
+</head>
+<body>
+ <div id="header" >
+ <div id="logo">
+ <a href="index.html" title="Ruby on Rails"><img src="images/rails_logo_remix.gif" alt="Rails" height="140" width="110" /></a>
+ </div>
+
+ <h1 id="site_title"><span>Ruby on Rails</span></h1>
+ <h2 id="site_title_tagline">Sustainable productivity for web-application development</h2>
+
+ <ul id="navMain">
+ <li class="first-child"><a href="http://www.rubyonrails.org/" title="Ruby on Rails" class="ruby_on_rails">Ruby on Rails</a></li>
+ <li><a class="manuals" href="index.html" title="Manuals Index">Guides Index</a></li>
+ </ul>
+ </div>
+
+ <div id="container">
+
+ <div id="sidebar">
+ <h2>Chapters</h2>
+ <ol>
+ <li>
+ <a href="#_application_architecture">Application Architecture</a>
+ <ul>
+
+ <li><a href="#_rack_integration">Rack Integration</a></li>
+
+ <li><a href="#_renewed_support_for_rails_engines">Renewed Support for Rails Engines</a></li>
+
+ </ul>
+ </li>
+ <li>
+ <a href="#_documentation">Documentation</a>
+ </li>
+ <li>
+ <a href="#_active_record">Active Record</a>
+ <ul>
+
+ <li><a href="#_nested_transactions">Nested Transactions</a></li>
+
+ <li><a href="#_dynamic_scopes">Dynamic Scopes</a></li>
+
+ <li><a href="#_default_scopes">Default Scopes</a></li>
+
+ <li><a href="#_multiple_conditions_for_callbacks">Multiple Conditions for Callbacks</a></li>
+
+ <li><a href="#_find_with_having">Find with having</a></li>
+
+ <li><a href="#_hash_conditions_for_tt_has_many_tt_relationships">Hash Conditions for <tt>has_many</tt> relationships</a></li>
+
+ <li><a href="#_other_active_record_changes">Other Active Record Changes</a></li>
+
+ </ul>
+ </li>
+ <li>
+ <a href="#_action_controller">Action Controller</a>
+ <ul>
+
+ <li><a href="#_unified_rendering">Unified Rendering</a></li>
+
+ <li><a href="#_application_controller_renamed">Application Controller Renamed</a></li>
+
+ <li><a href="#_more_efficient_routing">More Efficient Routing</a></li>
+
+ <li><a href="#_rack_based_lazy_loaded_sessions">Rack-based Lazy-loaded Sessions</a></li>
+
+ <li><a href="#_mime_type_handling_changes">MIME Type Handling Changes</a></li>
+
+ <li><a href="#_optimization_of_tt_respond_to_tt">Optimization of <tt>respond_to</tt></a></li>
+
+ <li><a href="#_improved_caching_performance">Improved Caching Performance</a></li>
+
+ <li><a href="#_other_action_controller_changes">Other Action Controller Changes</a></li>
+
+ </ul>
+ </li>
+ <li>
+ <a href="#_action_view">Action View</a>
+ <ul>
+
+ <li><a href="#_smart_rendering">Smart Rendering</a></li>
+
+ <li><a href="#_prompts_for_date_select_helpers">Prompts for Date Select Helpers</a></li>
+
+ <li><a href="#_assettag_timestamp_caching">AssetTag Timestamp Caching</a></li>
+
+ <li><a href="#_asset_hosts_as_objects">Asset Hosts as Objects</a></li>
+
+ <li><a href="#_other_action_view_changes">Other Action View Changes</a></li>
+
+ </ul>
+ </li>
+ <li>
+ <a href="#_active_support">Active Support</a>
+ <ul>
+
+ <li><a href="#_object_try">Object#try</a></li>
+
+ <li><a href="#_object_tap_backport">Object#tap Backport</a></li>
+
+ <li><a href="#_fractional_seconds_for_timewithzone">Fractional seconds for TimeWithZone</a></li>
+
+ <li><a href="#_json_key_quoting">JSON Key Quoting</a></li>
+
+ <li><a href="#_other_active_support_changes">Other Active Support Changes</a></li>
+
+ </ul>
+ </li>
+ <li>
+ <a href="#_railties">Railties</a>
+ <ul>
+
+ <li><a href="#_rails_metal">Rails Metal</a></li>
+
+ <li><a href="#_application_templates">Application Templates</a></li>
+
+ <li><a href="#_quieter_backtraces">Quieter Backtraces</a></li>
+
+ <li><a href="#_faster_boot_time_in_development_mode_with_lazy_loading_autoload">Faster Boot Time in Development Mode with Lazy Loading/Autoload</a></li>
+
+ <li><a href="#_other_railties_changes">Other Railties Changes</a></li>
+
+ </ul>
+ </li>
+ <li>
+ <a href="#_deprecated">Deprecated</a>
+ </li>
+ <li>
+ <a href="#_credits">Credits</a>
+ </li>
+ </ol>
+ </div>
+
+ <div id="content">
+ <h1>Ruby on Rails 2.3 Release Notes</h1>
+ <div id="preamble">
+<div class="sectionbody">
+<div class="paragraph"><p>Rails 2.3 delivers a variety of new and improved features, including pervasive Rack integration, refreshed support for Rails Engines, nested transactions for Active Record, dynamic and default scopes, unified rendering, more efficient routing, application templates, and quiet backtraces. 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>
+</div>
+<h2 id="_application_architecture">1. Application Architecture</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>There are two major changes in the architecture of Rails applications: complete integration of the <a href="http://rack.rubyforge.org/">Rack</a> modular web server interface, and renewed support for Rails Engines.</p></div>
+<h3 id="_rack_integration">1.1. Rack Integration</h3>
+<div class="paragraph"><p>Rails has now broken with its CGI past, and uses Rack everywhere. This required and resulted in a tremendous number of internal changes (but if you use CGI, don&#8217;t worry; Rails now supports CGI through a proxy interface.) Still, this is a major change to Rails internals. After upgrading to 2.3, you should test on your local environment and your production environment. Some things to test:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Sessions
+</p>
+</li>
+<li>
+<p>
+Cookies
+</p>
+</li>
+<li>
+<p>
+File uploads
+</p>
+</li>
+<li>
+<p>
+JSON/XML APIs
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>Here&#8217;s a summary of the rack-related changes:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+<tt>script/server</tt> has been switched to use Rack, which means it supports any Rack compatible server. <tt>script/server</tt> will also pick up a rackup configuration file if one exists. By default, it will look for a <tt>config.ru</tt> file, but you can override this with the <tt>-c</tt> switch.
+</p>
+</li>
+<li>
+<p>
+The FCGI handler goes through Rack
+</p>
+</li>
+<li>
+<p>
+ActionController::Dispatcher maintains its own default middleware stack. Middlewares can be injected in, reordered, and removed. The stack is compiled into a chain on boot. You can configure the middleware stack in <tt>environment.rb</tt>
+</p>
+</li>
+<li>
+<p>
+The <tt>rake middleware</tt> task has been added to inspect the middleware stack. This is useful for debugging the order of the middleware stack.
+</p>
+</li>
+<li>
+<p>
+The integration test runner has been modified to execute the entire middleware and application stack. This makes integration tests perfect for testing Rack middleware.
+</p>
+</li>
+<li>
+<p>
+<tt>ActionController::CGIHandler</tt> is a backwards compatible CGI wrapper around Rack. The <tt>CGIHandler</tt> is meant to take an old CGI object and converts its environment information into a Rack compatible form.
+</p>
+</li>
+<li>
+<p>
+<tt>CgiRequest</tt> and <tt>CgiResponse</tt> have been removed
+</p>
+</li>
+<li>
+<p>
+Session stores are now lazy loaded. If you never access the session object during a request, it will never attempt to load the session data (parse the cookie, load the data from memcache, or lookup an Active Record object).
+</p>
+</li>
+<li>
+<p>
+<tt>CGI::Session::CookieStore</tt> has been replaced by <tt>ActionController::Session::CookieStore</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>CGI::Session::MemCacheStore</tt> has been replaced by <tt>ActionController::Session::MemCacheStore</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>CGI::Session::ActiveRecordStore</tt> has been replaced by <tt>ActiveRecord::SessionStore</tt>
+</p>
+</li>
+<li>
+<p>
+You can still change you session store with <tt>ActionController::Base.session_store = :active_record_store</tt>
+</p>
+</li>
+<li>
+<p>
+Default sessions options are still set with <tt>ActionController::Base.session = { :key =&gt; "..." }</tt>
+</p>
+</li>
+<li>
+<p>
+The mutex that normally wraps your entire request has been moved into middleware, <tt>ActionController::Lock</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>ActionController::AbstractRequest</tt> and <tt>ActionController::Request</tt> have been unified. The new <tt>ActionController::Request</tt> inherits from <tt>Rack::Request</tt>. This affects access to <tt>response.headers[<em>type</em>]</tt> in test requests. Use <tt>response.content_type</tt> instead.
+</p>
+</li>
+<li>
+<p>
+<tt>ActiveRecord::QueryCache</tt> middleware is automatically inserted onto the middleware stack if <tt>ActiveRecord</tt> has been loaded. This middleware sets up and flushes the per-request Active Record query cache.
+</p>
+</li>
+<li>
+<p>
+The Rails router and controller classes follow the Rack spec. You can call a controller directly with <tt>SomeController.call(env)</tt>. The router stores the routing parameters in <tt>rack.routing_args</tt>.
+</p>
+</li>
+<li>
+<p>
+<tt>ActionController::Request</tt> inherits from <tt>Rack::Request</tt>
+</p>
+</li>
+<li>
+<p>
+Instead of <tt>config.action_controller.session = { :session_key =&gt; <em>foo</em>, ...</tt> use <tt>config.action_controller.session = { :key =&gt; <em>foo</em>, ...</tt>
+</p>
+</li>
+<li>
+<p>
+Using the <tt>ParamsParser</tt> middleware preprocesses any XML, JSON, or YAML requests so they can be read normally with any <tt>Rack::Request</tt> object after it.
+</p>
+</li>
+</ul></div>
+<h3 id="_renewed_support_for_rails_engines">1.2. Renewed Support for Rails Engines</h3>
+<div class="paragraph"><p>After some versions without an upgrade, Rails 2.3 offers some new features for Rails Engines (Rails applications that can be embedded within other applications). First, routing files in engines are automatically loaded and reloaded now, just like your <tt>routes.rb</tt> file (this also applies to routing files in other plugins). Second, if your plugin has an app folder, then app/[models|controllers|helpers] will automatically be added to the Rails load path. Engines also support adding view paths now.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://www.loudthinking.com/">David Heinemeier Hansson</a>
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_documentation">2. Documentation</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The <a href="http://guides.rubyonrails.org/">Ruby on Rails guides</a> project has published several additional guides for Rails 2.3. In addition, a <a href="http://guides.rails.info/">separate site</a> maintains updated copies of the Guides for Edge Rails. Other documentation efforts include a relaunch of the <a href="http://newwiki.rubyonrails.org/">Rails wiki</a> and early planning for a Rails Book.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+More Information: <a href="http://weblog.rubyonrails.org/2009/1/15/rails-documentation-projects">Rails Documentation Projects</a>
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_active_record">3. Active Record</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Active Record gets quite a number of new features and bug fixes in Rails 2.3. The highlights include nested transactions, dynamic scopes, and default scopes.</p></div>
+<h3 id="_nested_transactions">3.1. Nested Transactions</h3>
+<div class="paragraph"><p>Active Record now supports nested transactions, a much-requested feature. Now you can write code 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>User<span style="color: #990000">.</span>transaction <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ User<span style="color: #990000">.</span>create<span style="color: #990000">(:</span>username <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Admin'</span><span style="color: #990000">)</span>
+ User<span style="color: #990000">.</span>transaction<span style="color: #990000">(:</span>requires_new <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span>
+ User<span style="color: #990000">.</span>create<span style="color: #990000">(:</span>username <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Regular'</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">raise</span></span> ActiveRecord<span style="color: #990000">::</span>Rollback
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+ User<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">)</span> <span style="font-style: italic"><span style="color: #9A1900"># =&gt; Returns only Admin</span></span></tt></pre></div></div>
+<div class="paragraph"><p>Nested transactions let you roll back an inner transaction without affecting the state of the outer transaction. If you want a transaction to be nested, you must explicitly add the <tt>:requires_new</tt> option; otherwise, a nested transaction simply becomes part of the parent transaction (as it does currently on Rails 2.2). Under the covers, nested transactions are <a href="http://rails.lighthouseapp.com/projects/8994/tickets/383">using savepoints</a>, so they&#8217;re supported even on databases that don&#8217;t have true nested transactions. There is also a bit of magic going on to make these transactions play well with transactional fixtures during testing.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributors: <a href="http://www.workingwithrails.com/person/4985-jonathan-viney">Jonathan Viney</a> and <a href="http://izumi.plan99.net/blog/">Hongli Lai</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_dynamic_scopes">3.2. Dynamic Scopes</h3>
+<div class="paragraph"><p>You know about dynamic finders in Rails (which allow you to concoct methods like <tt>find_by_color_and_flavor</tt> on the fly) and named scopes (which allow you to encapsulate reusable query conditions into friendly names like <tt>currently_active</tt>). Well, now you can have dynamic scope methods. The idea is to put together syntax that allows filtering on the fly &lt;i&gt;and&lt;/i&gt; method chaining. 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>Order<span style="color: #990000">.</span>scoped_by_customer_id<span style="color: #990000">(</span><span style="color: #993399">12</span><span style="color: #990000">)</span>
+Order<span style="color: #990000">.</span>scoped_by_customer_id<span style="color: #990000">(</span><span style="color: #993399">12</span><span style="color: #990000">).</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>conditions <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"status = 'open'"</span><span style="color: #990000">)</span>
+Order<span style="color: #990000">.</span>scoped_by_customer_id<span style="color: #990000">(</span><span style="color: #993399">12</span><span style="color: #990000">).</span>scoped_by_status<span style="color: #990000">(</span><span style="color: #FF0000">"open"</span><span style="color: #990000">)</span></tt></pre></div></div>
+<div class="paragraph"><p>There&#8217;s nothing to define to use dynamic scopes: they just work.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://evilmartians.com/">Yaroslav Markin</a>
+</p>
+</li>
+<li>
+<p>
+More Information: <a href="http://ryandaigle.com/articles/2008/12/29/what-s-new-in-edge-rails-dynamic-scope-methods">What&#8217;s New in Edge Rails: Dynamic Scope Methods</a>.
+</p>
+</li>
+</ul></div>
+<h3 id="_default_scopes">3.3. Default Scopes</h3>
+<div class="paragraph"><p>Rails 2.3 will introduce the notion of <em>default scopes</em> similar to named scopes, but applying to all named scopes or find methods within the model. For example, you can write <tt>default_scope :order =&gt; <em>name ASC</em></tt> and any time you retrieve records from that model they&#8217;ll come out sorted by name (unless you override the option, of course).</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: Paweł Kondzior
+</p>
+</li>
+<li>
+<p>
+More Information: <a href="http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping">What&#8217;s New in Edge Rails: Default Scoping</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_multiple_conditions_for_callbacks">3.4. Multiple Conditions for Callbacks</h3>
+<div class="paragraph"><p>When using Active Record callbacks, you can now combine <tt>:if</tt> and <tt>:unless</tt> options on the same callback, and supply multiple conditions as an array:</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>before_save <span style="color: #990000">:</span>update_credit_rating<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: #990000">:</span>active<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> <span style="color: #990000">[:</span>admin<span style="color: #990000">,</span> <span style="color: #990000">:</span>cash_only<span style="color: #990000">]</span></tt></pre></div></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: L. Caviola
+</p>
+</li>
+</ul></div>
+<h3 id="_find_with_having">3.5. Find with having</h3>
+<div class="paragraph"><p>Rails now has a <tt>:having</tt> option on find (as well as on <tt>has_many</tt> and <tt>has_and_belongs_to_many</tt> associations) for filtering records in grouped finds. As those with heavy SQL backgrounds know, this allows filtering based on grouped results:</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>developers <span style="color: #990000">=</span> Developer<span style="color: #990000">.</span>find<span style="color: #990000">(:</span>all<span style="color: #990000">,</span> <span style="color: #990000">:</span>group <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"salary"</span><span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>having <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"sum(salary) &gt; 10000"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>select <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"salary"</span><span style="color: #990000">)</span></tt></pre></div></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://github.com/miloops">Emilio Tagua</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_hash_conditions_for_tt_has_many_tt_relationships">3.6. Hash Conditions for <tt>has_many</tt> relationships</h3>
+<div class="paragraph"><p>You can once again use a hash in conditions for a <tt>has_many</tt> relationship:</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>has_many <span style="color: #990000">:</span>orders<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>status <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'confirmed'</span><span style="color: #FF0000">}</span></tt></pre></div></div>
+<div class="paragraph"><p>That worked in Rails 2.1, fails in Rails 2.2, and will now work again in Rails 2.3 (if you&#8217;re dealing with this issue in Rails 2.2, you can use a string rather than a hash to specify conditions).</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://www.spacevatican.org/">Frederick Cheung</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_other_active_record_changes">3.7. Other Active Record Changes</h3>
+<div class="ulist"><ul>
+<li>
+<p>
+An extra <tt>AS</tt> was removed from the code for has_and_belongs_to_many preloading, making it work better for some databases.
+</p>
+</li>
+<li>
+<p>
+<tt>ActiveRecord::Base#new_record?</tt> now returns false rather than nil when confronted with an existing record.
+</p>
+</li>
+<li>
+<p>
+A bug in quoting table names in some <tt>has_many :through</tt> associations was fixed.
+</p>
+</li>
+<li>
+<p>
+You can now specify a particular timestamp for <tt>updated_at</tt> timestamps: <tt>cust = Customer.create(:name =&gt; "ABC Industries", :updated_at =&gt; 1.day.ago)</tt>
+</p>
+</li>
+<li>
+<p>
+Better error messages on failed <tt>find_by_attribute!</tt> calls.
+</p>
+</li>
+<li>
+<p>
+Active Record&#8217;s <tt>to_xml</tt> support gets just a little bit more flexible with the addition of a <tt>:camelize</tt> option.
+</p>
+</li>
+<li>
+<p>
+A bug in canceling callbacks from <tt>before_update</tt> or +before_create_ was fixed.
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_action_controller">4. Action Controller</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Action Controller rolls out some significant changes to rendering, as well as improvements in routing and other areas, in this release.</p></div>
+<h3 id="_unified_rendering">4.1. Unified Rendering</h3>
+<div class="paragraph"><p><tt>ActionController::Base#render</tt> is a lot smarter about deciding what to render. Now you can just tell it what to render and expect to get the right results. In older versions of Rails, you often need to supply explicit information to render:</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>render <span style="color: #990000">:</span>file <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'/tmp/random_file.erb'</span>
+render <span style="color: #990000">:</span>template <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'other_controller/action'</span>
+render <span style="color: #990000">:</span>action <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'show'</span></tt></pre></div></div>
+<div class="paragraph"><p>Now in Rails 2.3, you can just supply what you want to render:</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>render <span style="color: #FF0000">'/tmp/random_file.erb'</span>
+render <span style="color: #FF0000">'other_controller/action'</span>
+render <span style="color: #FF0000">'show'</span>
+render <span style="color: #990000">:</span>show</tt></pre></div></div>
+<div class="paragraph"><p>Rails chooses between file, template, and action depending on whether there is a leading slash, an embedded slash, or no slash at all in what&#8217;s to be rendered. Note that you can also use a symbol instead of a string when rendering an action. Other rendering styles (<tt>:inline, :text, :update, :nothing, :json, :xml, :js</tt>) still require an explicit option.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://m.onkey.org/">Pratik Naik</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_application_controller_renamed">4.2. Application Controller Renamed</h3>
+<div class="paragraph"><p>If you&#8217;re one of the people who has always been bothered by the special-case naming of <tt>application.rb</tt>, rejoice! It&#8217;s been reworked to be application_controller.rb in Rails 2.3. In addition, there&#8217;s a new rake task, <tt>rake rails:update:application_controller</tt> to do this automatically for you - and it will be run as part of the normal <tt>rake rails:update</tt> process.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://www.loudthinking.com/">David Heinemeier Hansson</a>
+</p>
+</li>
+<li>
+<p>
+More Information:
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+<a href="http://afreshcup.com/2008/11/17/rails-2x-the-death-of-applicationrb/">The Death of Application.rb</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://ryandaigle.com/articles/2008/11/19/what-s-new-in-edge-rails-application-rb-duality-is-no-more">What&#8217;s New in Edge Rails: Application.rb Duality is no More</a>
+</p>
+</li>
+</ul></div>
+</li>
+</ul></div>
+<h3 id="_more_efficient_routing">4.3. More Efficient Routing</h3>
+<div class="paragraph"><p>There are a couple of significant routing changes in Rails 2.3. The <tt>formatted_</tt> route helpers are gone, in favor just passing in <tt>:format</tt> as an option. This cuts down the route generation process by 50% for any resource - and can save a substantial amount of memory (up to 100MB on large applications). If your code uses the <tt>formatted_</tt> helpers, it will still work for the time being - but that behavior is deprecated and your application will be more efficient if you rewrite those routes using the new standard. Another big change is that Rails now supports multiple routing files, not just routes.rb. You can use <tt>RouteSet#add_configuration_file</tt> to bring in more routes at any time - without clearing the currently-loaded routes. While this change is most useful for Engines, you can use it in any application that needs to load routes in batches.</p></div>
+<div class="paragraph"><p>Lead Contributors: <a href="http://blog.hungrymachine.com/">Aaron Batalion</a> and <a href="http://www.loudthinking.com/">David Heinemeier Hansson</a></p></div>
+<h3 id="_rack_based_lazy_loaded_sessions">4.4. Rack-based Lazy-loaded Sessions</h3>
+<div class="paragraph"><p>A big change pushed the underpinnings of Action Controller session storage down to the Rack level. This involved a good deal of work in the code, though it should be completely transparent to your Rails applications (as a bonus, some icky patches around the old CGI session handler got removed). It&#8217;s still significant, though, for one simple reason: non-Rails Rack applications have access to the same session storage handlers (and therefore the same session) as your Rails applications. In addition, sessions are now lazy-loaded (in line with the loading improvements to the rest of the framework). This means that you no longer need to explicitly disable sessions if you don&#8217;t want them; just don&#8217;t refer to them and they won&#8217;t load.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://joshpeek.com/">Josh Peek</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_mime_type_handling_changes">4.5. MIME Type Handling Changes</h3>
+<div class="paragraph"><p>There are a couple of changes to the code for handling MIME types in Rails. First, <tt>MIME::Type</tt> now implements the <tt>=~</tt> operator, making things much cleaner when you need to check for the presence of a type that has synonyms:</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">if</span></span> content_type <span style="color: #990000">&amp;&amp;</span> Mime<span style="color: #990000">::</span>JS <span style="color: #990000">=~</span> content_type
+ <span style="font-style: italic"><span style="color: #9A1900"># do something cool</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+Mime<span style="color: #990000">::</span>JS <span style="color: #990000">=~</span> <span style="color: #FF0000">"text/javascript"</span> <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span>
+Mime<span style="color: #990000">::</span>JS <span style="color: #990000">=~</span> <span style="color: #FF0000">"application/javascript"</span> <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span></tt></pre></div></div>
+<div class="paragraph"><p>The other change is that the framework now uses the <tt>Mime::JS</tt> when checking for javascript in various spots, making it handle those alternatives cleanly.</p></div>
+<div class="paragraph"><p>Lead Contributor: <a href="http://www.workingwithrails.com/person/5510-seth-fitzsimmons">Seth Fitzsimmons</a></p></div>
+<h3 id="_optimization_of_tt_respond_to_tt">4.6. Optimization of <tt>respond_to</tt></h3>
+<div class="paragraph"><p>In some of the first fruits of the Rails-Merb team merger, Rails 2.3 includes some optimizations for the <tt>respond_to</tt> method, which is of course heavily used in many Rails applications to allow your controller to format results differently based on the MIME type of the incoming request. After eliminating a call to <tt>method_missing</tt> and some profiling and tweaking, we&#8217;re seeing an 8% improvement in the number of requests per second served with a simple <tt>respond_to</tt> that switches between three formats. The best part? No change at all required to the code of your application to take advantage of this speedup.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://yehudakatz.com/">Yehuda Katz</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_improved_caching_performance">4.7. Improved Caching Performance</h3>
+<div class="paragraph"><p>Rails now keeps a per-request local cache of requests, cutting down on unnecessary reads and leading to better site performance. While this work was originally limited to <tt>MemCacheStore</tt>, it is available to any remote store than implements the required methods.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://www.motionstandingstill.com/">Nahum Wild</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_other_action_controller_changes">4.8. Other Action Controller Changes</h3>
+<div class="ulist"><ul>
+<li>
+<p>
+ETag handling has been cleaned up a bit: Rails will now skip sending an ETag header when there&#8217;s no body to the response or when sending files with <tt>send_file</tt>.
+</p>
+</li>
+<li>
+<p>
+The fact that Rails checks for IP spoofing can be a nuisance for sites that do heavy traffic with cell phones, because their proxies don&#8217;t generally set things up right. If that&#8217;s you, you can now set <tt>ActionController::Base.ip_spoofing_check = false</tt> to disable the check entirely.
+</p>
+</li>
+<li>
+<p>
+ActionController::Dispatcher now implements its own middleware stack, which you can see by running <tt>rake middleware</tt>.
+</p>
+</li>
+<li>
+<p>
+Cookie sessions now have persistent session identifiers, with API compatibility with the server-side stores.
+</p>
+</li>
+<li>
+<p>
+You can now use symbols for the <tt>:type</tt> option of <tt>send_file</tt> and <tt>send_data</tt>, like this: <tt>send_file("fabulous.png", :type =&gt; :png)</tt>.
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_action_view">5. Action View</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Action View in Rails 2.3 picks up improvements to <tt>render</tt>, more flexible prompts for the date select helpers, and a speedup in asset caching, among other things.</p></div>
+<h3 id="_smart_rendering">5.1. Smart Rendering</h3>
+<div class="paragraph"><p>The render method has been getting smarter over the years, and it&#8217;s even smarter now. If you have an object or a collection and an appropriate partial, and the naming matches up, you can now just render the object and things will work. For example, in Rails 2.3, these render calls will work in your view (assuming sensible naming):</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: #FF0000">&lt;% render @article %&gt;</span>
+<span style="color: #FF0000">&lt;% render @articles %&gt;</span></tt></pre></div></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://www.loudthinking.com/">David Heinemeier Hansson</a>
+</p>
+</li>
+<li>
+<p>
+More Information: <a href="http://ryandaigle.com/articles/2008/11/20/what-s-new-in-edge-rails-render-stops-being-high-maintenance">What&#8217;s New in Edge Rails: render Stops Being High-Maintenance</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_prompts_for_date_select_helpers">5.2. Prompts for Date Select Helpers</h3>
+<div class="paragraph"><p>In Rails 2.3, you can supply custom prompts for the various date select helpers (<tt>date_select</tt>, <tt>time_select</tt>, and <tt>datetime_select</tt>), the same way you can with collection select helpers. You can supply a prompt string or a hash of individual prompt strings for the various components. You can also just set <tt>:prompt</tt> to <tt>true</tt> to use the custom generic prompt:</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>select_datetime<span style="color: #990000">(</span>DateTime<span style="color: #990000">.</span>now<span style="color: #990000">,</span> <span style="color: #990000">:</span>prompt <span style="color: #990000">=&gt;</span> <span style="font-weight: bold"><span style="color: #0000FF">true</span></span><span style="color: #990000">)</span>
+
+select_datetime<span style="color: #990000">(</span>DateTime<span style="color: #990000">.</span>now<span style="color: #990000">,</span> <span style="color: #990000">:</span>prompt <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"Choose date and time"</span><span style="color: #990000">)</span>
+
+select_datetime<span style="color: #990000">(</span>DateTime<span style="color: #990000">.</span>now<span style="color: #990000">,</span> <span style="color: #990000">:</span>prompt <span style="color: #990000">=&gt;</span>
+ <span style="color: #FF0000">{</span><span style="color: #990000">:</span>day <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Choose day'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>month <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Choose month'</span><span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>year <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Choose year'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>hour <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Choose hour'</span><span style="color: #990000">,</span>
+ <span style="color: #990000">:</span>minute <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Choose minute'</span><span style="color: #FF0000">}</span><span style="color: #990000">)</span></tt></pre></div></div>
+<div class="paragraph"><p>Lead Contributor: <a href="http://samoliver.com/">Sam Oliver</a></p></div>
+<h3 id="_assettag_timestamp_caching">5.3. AssetTag Timestamp Caching</h3>
+<div class="paragraph"><p>You&#8217;re likely familiar with Rails' practice of adding timestamps to static asset paths as a "cache buster." This helps ensure that stale copies of things like images and stylesheets don&#8217;t get served out of the user&#8217;s browser cache when you change them on the server. You can now modify this behavior with the <tt>cache_asset_timestamps</tt> configuration option for Action View. If you enable the cache, then Rails will calculate the timestamp once when it first serves an asset, and save that value. This means fewer (expensive) file system calls to serve static assets - but it also means that you can&#8217;t modify any of the assets while the server is running and expect the changes to get picked up by clients.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://joshpeek.com/">Josh Peek</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_asset_hosts_as_objects">5.4. Asset Hosts as Objects</h3>
+<div class="paragraph"><p>Asset hosts get more flexible in edge Rails with the ability to declare an asset host as a specific object that responds to a call. This allows you to to implement any complex logic you need in your asset hosting.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://www.loudthinking.com/">David Heinemeier Hansson</a>
+</p>
+</li>
+<li>
+<p>
+More Information: <a href="http://github.com/dhh/asset-hosting-with-minimum-ssl/tree/master">asset-hosting-with-minimum-ssl</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_other_action_view_changes">5.5. Other Action View Changes</h3>
+<div class="ulist"><ul>
+<li>
+<p>
+Token generation for CSRF protection has been simplified; now Rails uses a simple random string generated by <tt>ActiveSupport::SecureRandom</tt> rather than mucking around with session IDs.
+</p>
+</li>
+<li>
+<p>
+<tt>auto_link</tt> now properly applies options (such as :target and :class) to generated e-mail links.
+</p>
+</li>
+<li>
+<p>
+The <tt>autolink</tt> helper has been refactored to make it a bit less messy and more intuitive.
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_active_support">6. Active Support</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Active Support has a few interesting changes, including the introduction of <tt>Object#try</tt>.</p></div>
+<h3 id="_object_try">6.1. Object#try</h3>
+<div class="paragraph"><p>A lot of folks have adopted the notion of using try() to attempt operations on objects - It&#8217;s especially helpful in views where you can avoid nil-checking by writing code like <tt>&lt;%= @person.try(:name) %&gt;</tt>. Well, now it&#8217;s baked right into Rails. As implemented in Rails, it raises <tt>NoMethodError</tt> on private methods and always returns <tt>nil</tt> if the object is nil.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://m.onkey.org/">Pratik Naik</a>
+</p>
+</li>
+<li>
+<p>
+More Information: <a href="http://ozmm.org/posts/try.html">try()</a>.
+</p>
+</li>
+</ul></div>
+<h3 id="_object_tap_backport">6.2. Object#tap Backport</h3>
+<div class="paragraph"><p><tt>Object#tap</tt> is an addition to "Ruby 1.9":http://www.ruby-doc.org/core-1.9/classes/Object.html#M000309 and 1.8.7 that is similar to the <tt>returning</tt> method that Rails has had for a while: it yields to a block, and then returns the object that was yielded. Rails now includes code to make this available under older versions of Ruby as well.</p></div>
+<div class="paragraph"><p>Lead Contributor: <a href="http://bitsweat.net/">Jeremy Kemper</a></p></div>
+<h3 id="_fractional_seconds_for_timewithzone">6.3. Fractional seconds for TimeWithZone</h3>
+<div class="paragraph"><p>The <tt>Time</tt> and <tt>TimeWithZone</tt> classes include an <tt>xmlschema</tt> method to return the time in an XML-friendly string. As of Rails 2.3, <tt>TimeWithZone</tt> supports the same argument for specifying the number of digits in the fractional second part of the returned string that <tt>Time</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><span style="color: #990000">&gt;&gt;</span> Time<span style="color: #990000">.</span>zone<span style="color: #990000">.</span>now<span style="color: #990000">.</span>xmlschema<span style="color: #990000">(</span><span style="color: #993399">6</span><span style="color: #990000">)</span>
+<span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"2009-01-16T13:00:06.13653Z"</span></tt></pre></div></div>
+<div class="paragraph"><p>Lead Contributor: <a href="http://www.workingwithrails.com/person/13536-nicholas-dainty">Nicholas Dainty</a></p></div>
+<h3 id="_json_key_quoting">6.4. JSON Key Quoting</h3>
+<div class="paragraph"><p>If you look up the spec on the "json.org" site, you&#8217;ll discover that all keys in a JSON structure must be strings, and they must be quoted with double quotes. Starting with Rails 2.3, we doe the right thing here, even with numeric keys.</p></div>
+<div class="paragraph"><p>Lead Contributor: <a href="http://www.koziarski.net/">Michael Koziarski</a></p></div>
+<h3 id="_other_active_support_changes">6.5. Other Active Support Changes</h3>
+<div class="ulist"><ul>
+<li>
+<p>
+You can use <tt>Enumerable#none?</tt> to check that none of the elements match the supplied block.
+</p>
+</li>
+<li>
+<p>
+If you&#8217;re using Active Support <a href="http://afreshcup.com/2008/10/19/coming-in-rails-22-delegate-prefixes/">delegates</a>, the new <tt>:allow_nil</tt> option lets you return nil instead of raising an exception when the target object is nil.
+</p>
+</li>
+<li>
+<p>
+<tt>ActiveSupport::OrderedHash</tt>: now implements <tt>each_key</tt> and <tt>each_value</tt>.
+</p>
+</li>
+<li>
+<p>
+<tt>ActiveSupport::MessageEncryptor</tt> provides a simple way to encrypt information for storage in an untrusted location (like cookies).
+</p>
+</li>
+<li>
+<p>
+Active Support&#8217;s <tt>from_xml</tt> no longer depends on XmlSimple. Instead, Rails now includes its own XmlMini implementation, with just the functionality that it requires. This lets Rails dispense with the bundled copy of XmlSimple that it&#8217;s been carting around.
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_railties">7. Railties</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>In addition to the Rack changes covered above, Railties (the core code of Rails itself) sports a number of significant changes, including Rails Metal, application templates, and quiet backtraces.</p></div>
+<h3 id="_rails_metal">7.1. Rails Metal</h3>
+<div class="paragraph"><p>Rails Metal is a new mechanism that provides superfast endpoints inside of your Rails applications. Metal classes bypass routing and Action Controller to give you raw speed (at the cost of all the things in Action Controller, of course). This builds on all of the recent foundation work to make Rails a Rack application with an exposed middleware stack.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://www.loudthinking.com/">David Heinemeier Hansson</a>
+</p>
+</li>
+<li>
+<p>
+More Information:
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+<a href="http://weblog.rubyonrails.org/2008/12/17/introducing-rails-metal">Introducing Rails Metal</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://soylentfoo.jnewland.com/articles/2008/12/16/rails-metal-a-micro-framework-with-the-power-of-rails-m">Rails Metal: a micro-framework with the power of Rails</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://www.railsinside.com/deployment/180-metal-super-fast-endpoints-within-your-rails-apps.html">Metal: Super-fast Endpoints within your Rails Apps</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://ryandaigle.com/articles/2008/12/18/what-s-new-in-edge-rails-rails-metal">What&#8217;s New in Edge Rails: Rails Metal</a>
+</p>
+</li>
+</ul></div>
+</li>
+</ul></div>
+<h3 id="_application_templates">7.2. Application Templates</h3>
+<div class="paragraph"><p>Rails 2.3 incorporates Jeremy McAnally&#8217;s "rg":http://github.com/jeremymcanally/rg/tree/master application generator. What this means is that we now have template-based application generation built right into Rails; if you have a set of plugins you include in every application (among many other use cases), you can just set up a template once and use it over and over again when you run the <tt>rails</tt> command. There&#8217;s also a rake task to apply a template to an existing 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 rails<span style="color: #990000">:</span>template LOCATION<span style="color: #990000">=~/</span>template<span style="color: #990000">.</span>rb</tt></pre></div></div>
+<div class="paragraph"><p>This will layer the changes from the template on top of whatever code the project already contains.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://www.jeremymcanally.com/">Jeremy McAnally</a>
+</p>
+</li>
+<li>
+<p>
+More Info:<a href="http://m.onkey.org/2008/12/4/rails-templates">Rails templates</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_quieter_backtraces">7.3. Quieter Backtraces</h3>
+<div class="paragraph"><p>Building on Thoughtbot&#8217;s "Quiet Backtrace":http://www.thoughtbot.com/projects/quietbacktrace plugin, which allows you to selectively remove lines from Test::Unit backtraces, Rails 2.3 implements <tt>ActiveSupport::BacktraceCleaner</tt> and <tt>Rails::BacktraceCleaner</tt> in core. This supports both filters (to perform regex-based substitutions on backtrace lines) and silencers (to remove backtrace lines entirely). Rails automatically adds silencers to get rid of the most common noise in a new application, and builds a <tt>config/backtrace_silencers.rb</tt> file to hold your own additions. This feature also enables prettier printing from any gem in the backtrace.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributor: <a href="http://www.loudthinking.com/">David Heinemeier Hansson</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_faster_boot_time_in_development_mode_with_lazy_loading_autoload">7.4. Faster Boot Time in Development Mode with Lazy Loading/Autoload</h3>
+<div class="paragraph"><p>Quite a bit of work was done to make sure that bits of Rails (and its dependencies) are only brought into memory when they&#8217;re actually needed. The core frameworks - Active Support, Active Record, Action Controller, Action Mailer and Action View - are now using <tt>autoload</tt> to lazy-load their individual classes. This work should help keep the memory footprint down and improve overall Rails performance.</p></div>
+<div class="paragraph"><p>You can also specify (by using the new <tt>preload_frameworks</tt> option) whether the core libraries should be autoloaded at startup. This defaults to <tt>false</tt> so that Rails autoloads itself piece-by-piece, but there are some circumstances where you still need to bring in everything at once - Passenger and JRuby both want to see all of Rails loaded together.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Lead Contributors: <a href="http://bitsweat.net/">Jeremy Kemper</a> and <a href="http://joshpeek.com/">Josh Peek</a>
+</p>
+</li>
+</ul></div>
+<h3 id="_other_railties_changes">7.5. Other Railties Changes</h3>
+<div class="ulist"><ul>
+<li>
+<p>
+The instructions for updating a CI server to build Rails have been updated and expanded.
+</p>
+</li>
+<li>
+<p>
+Internal Rails testing has been switched from <tt>Test::Unit::TestCase</tt> to <tt>ActiveSupport::TestCase</tt>, and the Rails core requires Mocha to test.
+</p>
+</li>
+<li>
+<p>
+The default <tt>environment.rb</tt> file has been decluttered.
+</p>
+</li>
+<li>
+<p>
+The dbconsole script now lets you use an all-numeric password without crashing.
+</p>
+</li>
+<li>
+<p>
+Rails.root now returns a Pathname object, which means you can use it directly with the join method to <a href="http://afreshcup.com/2008/12/05/a-little-rails_root-tidiness/">clean up existing code</a> that uses File.join.
+</p>
+</li>
+<li>
+<p>
+Various files in /public that deal with CGI and FCGI dispatching are no longer generated in every Rails application by default (you can still get them if you need them by adding <tt>--with-dispatches</tt> when you run the rails command, or add them later with <tt>rake rails:generate_dispatchers</tt>).
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_deprecated">8. Deprecated</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>A few pieces of older code are deprecated in this release:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+If you&#8217;re one of the (fairly rare) Rails developers who deploys in a fashion that depends on the inspector, reaper, and spawner scripts, you&#8217;ll need to know that those scripts are no longer included in core Rails. If you need them, you&#8217;ll be able to pick up copies via the <a href="http://github.com/rails/irs_process_scripts/tree">irs_process_scripts</a> plugin.
+</p>
+</li>
+<li>
+<p>
+<tt>render_component</tt> goes from "deprecated" to "nonexistent" in Rails 2.3. If you still need it, you can install the <a href="http://github.com/rails/render_component/tree/master">render_component plugin</a>.
+</p>
+</li>
+<li>
+<p>
+Support for Rails components has been removed.
+</p>
+</li>
+<li>
+<p>
+If you were one of the people who got used to running <tt>script/performance/request</tt> to look at performance based on integration tests, you need to learn a new trick: that script has been removed from core Rails now. There’s a new request_profiler plugin that you can install to get the exact same functionality back.
+</p>
+</li>
+<li>
+<p>
+<tt>ActionController::Base#session_enabled?</tt> is deprecated because sessions are lazy-loaded now.
+</p>
+</li>
+<li>
+<p>
+The <tt>:digest</tt> and <tt>:secret</tt> options to <tt>protect_from_forgery</tt> are deprecated and have no effect.
+</p>
+</li>
+<li>
+<p>
+Some integration test helpers have been removed. <tt>response.headers["Status"]</tt> and <tt>headers["Status"]</tt> will no longer return anything. Rack does not allow "Status" in its return headers. However you can still use the <tt>status</tt> and <tt>status_message</tt> helpers. <tt>response.headers["cookie"]</tt> and <tt>headers["cookie"]</tt> will no longer return any CGI cookies. You can inspect <tt>headers["Set-Cookie"]</tt> to see the raw cookie header or use the <tt>cookies</tt> helper to get a hash of the cookies sent to the client.
+</p>
+</li>
+</ul></div>
+</div>
+<h2 id="_credits">9. Credits</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Release notes compiled by <a href="http://afreshcup.com">Mike Gunderloy</a></p></div>
+</div>
+
+ </div>
+ </div>
+</body>
+</html>
diff --git a/railties/doc/guides/html/action_mailer_basics.html b/railties/doc/guides/html/action_mailer_basics.html
index 56451818eb..317f135e4c 100644
--- a/railties/doc/guides/html/action_mailer_basics.html
+++ b/railties/doc/guides/html/action_mailer_basics.html
@@ -50,6 +50,12 @@
<li>
<a href="#_mailer_testing">Mailer Testing</a>
</li>
+ <li>
+ <a href="#_epilogue">Epilogue</a>
+ </li>
+ <li>
+ <a href="#_changelog">Changelog</a>
+ </li>
</ol>
</div>
@@ -189,6 +195,37 @@ http://www.gnu.org/software/src-highlite -->
</div>
<h2 id="_mailer_testing">3. Mailer Testing</h2>
<div class="sectionbody">
+<div class="paragraph"><p>Testing mailers involves 2 things. One is that the mail was queued and the other that the body contains what we expect it to contain. With that in mind, we could test our example mailer from above 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><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> UserMailerTest <span style="color: #990000">&lt;</span> ActionMailer<span style="color: #990000">::</span>TestCase
+ tests UserMailer
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> test_welcome_email
+ user <span style="color: #990000">=</span> users<span style="color: #990000">(:</span>some_user_in_your_fixtures<span style="color: #990000">)</span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Send the email, then test that it got queued</span></span>
+ email <span style="color: #990000">=</span> UserMailer<span style="color: #990000">.</span>deliver_welcome_email<span style="color: #990000">(</span>user<span style="color: #990000">)</span>
+ assert <span style="color: #990000">!</span>ActionMailer<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>deliveries<span style="color: #990000">.</span>empty?
+
+ <span style="font-style: italic"><span style="color: #9A1900"># Test the body of the sent email contains what we expect it to</span></span>
+ assert_equal <span style="color: #990000">[</span><span style="color: #009900">@user</span><span style="color: #990000">.</span>email<span style="color: #990000">],</span> email<span style="color: #990000">.</span>to
+ assert_equal <span style="color: #FF0000">"Welcome to My Awesome Site"</span><span style="color: #990000">,</span> email<span style="color: #990000">.</span>subject
+ assert email<span style="color: #990000">.</span>body <span style="color: #990000">=~</span> <span style="color: #FF6600">/Welcome to example.com, #{user.first_name}/</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="paragraph"><p>What have we done? Well, we sent the email and stored the returned object in the email variable. We then ensured that it was sent (the first assert), then, in the second batch of assertion, we ensure that the email does indeed contain the values that we expect.</p></div>
+</div>
+<h2 id="_epilogue">4. Epilogue</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>This guide presented how to create a mailer and how to test it. In reality, you may find that writing your tests before you actually write your code to be a rewarding experience. It may take some time to get used to TDD (Test Driven Development), but coding this way achieves two major benefits. Firstly, you know that the code does indeed work, because the tests fail (because there&#8217;s no code), then they pass, because the code that satisfies the tests was written. Secondly, when you start with the tests, you don&#8217;t have to make time AFTER you write the code, to write the tests, then never get around to it. The tests are already there and testing has now become part of your coding regimen.</p></div>
+</div>
+<h2 id="_changelog">5. Changelog</h2>
+<div class="sectionbody">
+<div class="paragraph"><p><a href="http://rails.lighthouseapp.com/projects/16213/tickets/25">Lighthouse ticket</a></p></div>
</div>
</div>
diff --git a/railties/doc/guides/html/actioncontroller_basics.html b/railties/doc/guides/html/actioncontroller_basics.html
index f5b25a4d7a..201a2c62f0 100644
--- a/railties/doc/guides/html/actioncontroller_basics.html
+++ b/railties/doc/guides/html/actioncontroller_basics.html
@@ -88,7 +88,14 @@
</ul>
</li>
<li>
- <a href="#_http_basic_authentication">HTTP Basic Authentication</a>
+ <a href="#_http_authentications">HTTP Authentications</a>
+ <ul>
+
+ <li><a href="#_http_basic_authentication">HTTP Basic Authentication</a></li>
+
+ <li><a href="#_http_digest_authentication">HTTP Digest Authentication</a></li>
+
+ </ul>
</li>
<li>
<a href="#_streaming_and_file_downloads">Streaming and File Downloads</a>
@@ -803,9 +810,23 @@ 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>
</div>
-<h2 id="_http_basic_authentication">10. HTTP Basic Authentication</h2>
+<h2 id="_http_authentications">10. HTTP Authentications</h2>
<div class="sectionbody">
-<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="paragraph"><p>Rails comes with two built-in HTTP authentication mechanisms :</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Basic Authentication
+</p>
+</li>
+<li>
+<p>
+Digest Authentication
+</p>
+</li>
+</ul></div>
+<h3 id="_http_basic_authentication">10.1. HTTP Basic Authentication</h3>
+<div class="paragraph"><p>HTTP Basic authentication 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
@@ -817,7 +838,7 @@ http://www.gnu.org/software/src-highlite -->
before_filter <span style="color: #990000">:</span>authenticate
-private
+ private
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> authenticate
authenticate_or_request_with_http_basic <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>username<span style="color: #990000">,</span> password<span style="color: #990000">|</span>
@@ -827,6 +848,29 @@ private
<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>
+<h3 id="_http_digest_authentication">10.2. HTTP Digest Authentication</h3>
+<div class="paragraph"><p>HTTP Digest authentication is superior to the Basic authentication as it does not require the client to send unencrypted password over the network. Using Digest authentication with Rails is quite easy and only requires using one method, <tt>authenticate_or_request_with_http_digest</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">class</span></span> AdminController <span style="color: #990000">&lt;</span> ApplicationController
+
+ USERS <span style="color: #990000">=</span> <span style="color: #FF0000">{</span> <span style="color: #FF0000">"lifo"</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"world"</span> <span style="color: #FF0000">}</span>
+
+ before_filter <span style="color: #990000">:</span>authenticate
+
+ private
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> authenticate
+ authenticate_or_request_with_http_digest <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>username<span style="color: #990000">|</span>
+ USERS<span style="color: #990000">[</span>username<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>
+
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
+<div class="paragraph"><p>As seen in the example above, <tt>authenticate_or_request_with_http_digest</tt> block takes only one argument - the username. And the block returns the password. Returning <tt>false</tt> or <tt>nil</tt> from the <tt>authenticate_or_request_with_http_digest</tt> will cause authentication failure.</p></div>
</div>
<h2 id="_streaming_and_file_downloads">11. Streaming and File Downloads</h2>
<div class="sectionbody">
diff --git a/railties/doc/guides/html/active_record_basics.html b/railties/doc/guides/html/active_record_basics.html
index 04f1e3e838..7ec77781ce 100644
--- a/railties/doc/guides/html/active_record_basics.html
+++ b/railties/doc/guides/html/active_record_basics.html
@@ -31,13 +31,27 @@
<h2>Chapters</h2>
<ol>
<li>
- <a href="#_orm_the_blueprint_of_active_record">ORM The Blueprint of Active Record</a>
+ <a href="#_what_8217_s_active_record">What&#8217;s Active Record</a>
</li>
<li>
- <a href="#_active_record_the_engine_of_rails">Active Record The Engine of Rails</a>
+ <a href="#_object_relational_mapping">Object Relational Mapping</a>
+ </li>
+ <li>
+ <a href="#_activerecord_as_an_orm_framework">ActiveRecord as an ORM framework</a>
+ </li>
+ <li>
+ <a href="#_active_record_inside_the_mvc_model">Active Record inside the MVC model</a>
+ </li>
+ <li>
+ <a href="#_creating_activerecord_models">Creating ActiveRecord models</a>
+ </li>
+ <li>
+ <a href="#_convention_over_configuration_in_activerecord">Convention over Configuration in ActiveRecord</a>
<ul>
- <li><a href="#_rails_active_record_conventions">Rails Active Record Conventions</a></li>
+ <li><a href="#_naming_conventions">Naming Conventions</a></li>
+
+ <li><a href="#_schema_conventions">Schema Conventions</a></li>
</ul>
</li>
@@ -66,146 +80,227 @@
<h1>Active Record Basics</h1>
<div id="preamble">
<div class="sectionbody">
-<div class="paragraph"><p>Active Record is a design pattern that mitigates the mind-numbing mental gymnastics often needed to get your application to communicate with a database. This guide uses a mix of real-world examples, metaphors and detailed explanations of the actual Rails source code to help you make the most of ActiveRecord.</p></div>
-<div class="paragraph"><p>After reading this guide readers should have a strong grasp of the Active Record pattern and how it can be used with or without Rails. Hopefully, some of the philosophical and theoretical intentions discussed here will also make them a stronger and better developer.</p></div>
+<div class="paragraph"><p>This guide will give you a strong grasp of the Active Record pattern and how it can be used with or without Rails. Hopefully, some of the philosophical and theoretical intentions discussed here will also make you a stronger and better developer.</p></div>
+<div class="paragraph"><p>After reading this guide we hope that you&#8217;ll be able to:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Understand the way Active Record fits into the MVC model.
+</p>
+</li>
+<li>
+<p>
+Create basic Active Record models and map them with your database tables.
+</p>
+</li>
+<li>
+<p>
+Use your models to execute CRUD (Create, Read, Update and Delete) database operations.
+</p>
+</li>
+<li>
+<p>
+Follow the naming conventions used by Rails to make developing database applications easier and obvious.
+</p>
+</li>
+<li>
+<p>
+Take advantage of the way Active Record maps it&#8217;s attributes with the database tables' columns to implement your application&#8217;s logic.
+</p>
+</li>
+<li>
+<p>
+Use Active Record with legacy databases that do not follow the Rails naming conventions.
+</p>
+</li>
+</ul></div>
</div>
</div>
-<h2 id="_orm_the_blueprint_of_active_record">1. ORM The Blueprint of Active Record</h2>
+<h2 id="_what_8217_s_active_record">1. What&#8217;s Active Record</h2>
<div class="sectionbody">
-<div class="paragraph"><p>If Active Record is the engine of Rails then ORM is the blueprint of that engine. ORM is short for “Object Relational Mapping” and is a programming concept used to make structures within a system relational. As a thought experiment imagine the components that make up a typical car. There are doors, seats, windows, engines etc. Viewed independently they are simple parts, yet when bolted together through the aid of a blueprint, the parts become a more complex device. ORM is the blueprint that describes how the individual parts relate to one another and in some cases infers the part’s purpose through the way the associations are described.</p></div>
+<div class="paragraph"><p>Rails' ActiveRecord is an implementation of Martin Fowler&#8217;s <a href="http://martinfowler.com/eaaCatalog/activeRecord.html">Active Record Design Pattern</a>. This pattern is based on the idea of creating relations between the database and the application in the following way:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Each database table is mapped to a class.
+</p>
+</li>
+<li>
+<p>
+Each table column is mapped to an attribute of this class.
+</p>
+</li>
+<li>
+<p>
+Each instance of this class is mapped to a single row in the database table.
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>The definition of the Active Record pattern in Martin Fowler&#8217;s words:</p></div>
+<div class="paragraph"><p>"<em>An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data."</em></p></div>
</div>
-<h2 id="_active_record_the_engine_of_rails">2. Active Record The Engine of Rails</h2>
+<h2 id="_object_relational_mapping">2. Object Relational Mapping</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Active Record is a design pattern used to access data within a database. The name “Active Record” was coined by Martin Fowler in his book “Patterns of Enterprise Application Architecture”. Essentially, when a record is returned from the database instead of being just the data it is wrapped in a class, which gives you methods to control that data with. The rails framework is built around the MVC (Model View Controller) design patten and the Active Record is used as the default Model.</p></div>
-<div class="paragraph"><p>The Rails community added several useful concepts to their version of Active Record, including inheritance and associations, which are extremely useful for web applications. The associations are created by using a DSL (domain specific language) of macros, and inheritance is achieved through the use of STI (Single Table Inheritance) at the database level.</p></div>
-<div class="paragraph"><p>By following a few simple conventions the Rails Active Record will automatically map between:</p></div>
+<div class="paragraph"><p>The relation between databases and object-oriented software is called ORM, which is short for "Object Relational Mapping". The purpose of an ORM framework is to minimize the mismatch existent between relational databases and object-oriented software. In applications with a domain model, we have objects that represent both the state of the system and the behaviour of the real world elements that were modeled through these objects. Since we need to store the system&#8217;s state somehow, we can use relational databases, which are proven to be an excelent approach to data management. Usually this may become a very hard thing to do, since we need to create an object-oriented model of everything that lives in the database, from simple columns to complicated relations between different tables. Doing this kind of thing by hand is a tedious and error prone job. This is where an ORM framework comes in.</p></div>
+</div>
+<h2 id="_activerecord_as_an_orm_framework">3. ActiveRecord as an ORM framework</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>ActiveRecord gives us several mechanisms, being the most important ones the hability to:</p></div>
<div class="ulist"><ul>
<li>
<p>
-Classes &amp; Database Tables
+Represent models.
+</p>
+</li>
+<li>
+<p>
+Represent associations between these models.
</p>
</li>
<li>
<p>
-Class attributes &amp; Database Table Columns
+Represent inheritance hierarquies through related models.
+</p>
+</li>
+<li>
+<p>
+Validate models before they get recorded to the database.
+</p>
+</li>
+<li>
+<p>
+Perform database operations in an object-oriented fashion.
</p>
</li>
</ul></div>
-<h3 id="_rails_active_record_conventions">2.1. Rails Active Record Conventions</h3>
-<div class="paragraph"><p>Here are the key conventions to consider when using Active Record.</p></div>
-<h4 id="_naming_conventions">2.1.1. Naming Conventions</h4>
-<div class="paragraph"><p>Database Table - Plural with underscores separating words i.e. (book_clubs)
-Model Class - Singular with the first letter of each word capitalized i.e. (BookClub)
-Here are some additional Examples:</p></div>
-<div class="tableblock">
-<table rules="all"
-frame="hsides"
-cellspacing="0" cellpadding="4">
-<col width="160" />
-<col width="182" />
-<thead>
- <tr>
- <th align="left">
- Model / Class
- </th>
- <th align="left">
- Table / Schema
- </th>
- </tr>
-</thead>
-<tbody valign="top">
- <tr>
- <td align="left">
- Post
- </td>
- <td align="left">
- posts
- </td>
- </tr>
- <tr>
- <td align="left">
- LineItem
- </td>
- <td align="left">
- line_items
- </td>
- </tr>
- <tr>
- <td align="left">
- Deer
- </td>
- <td align="left">
- deer
- </td>
- </tr>
- <tr>
- <td align="left">
- Mouse
- </td>
- <td align="left">
- mice
- </td>
- </tr>
- <tr>
- <td align="left">
- Person
- </td>
- <td align="left">
- people
- </td>
- </tr>
-</tbody>
-</table>
+<div class="paragraph"><p>It&#8217;s easy to see that the Rails Active Record implementation goes way beyond the basic description of the Active Record Pattern.</p></div>
+</div>
+<h2 id="_active_record_inside_the_mvc_model">4. Active Record inside the MVC model</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Active Record plays the role of model inside the MVC structure followed by Rails applications. Since model objects should encapsulate both state and logic of your applications, it&#8217;s ActiveRecord responsability to deliver you the easiest possible way to recover this data from the database.</p></div>
+</div>
+<h2 id="_creating_activerecord_models">5. Creating ActiveRecord models</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>It&#8217;s very easy to create ActiveRecord models. All you have to do is to subclass the ActiveRecord::Base class and you&#8217;re good to go:</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> Product <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #990000">;</span> <span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
+<div class="paragraph"><p>This will create a <tt>Product</tt> model, mapped to a <strong>products</strong> table at the database. By doing this you&#8217;ll also have the hability to map the columns of each row in that table with the attributes of the instances of your model. So, suppose that the <strong>products</strong> table was created using a SQL sentence 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">CREATE</span></span> <span style="font-weight: bold"><span style="color: #0000FF">TABLE</span></span> products <span style="color: #990000">(</span>
+ id <span style="color: #009900">int</span><span style="color: #990000">(</span><span style="color: #993399">11</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">NOT</span></span> <span style="font-weight: bold"><span style="color: #0000FF">NULL</span></span> <span style="font-weight: bold"><span style="color: #0000FF">auto_increment</span></span><span style="color: #990000">,</span>
+ name <span style="color: #009900">varchar</span><span style="color: #990000">(</span><span style="color: #993399">255</span><span style="color: #990000">),</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">PRIMARY</span></span> <span style="font-weight: bold"><span style="color: #0000FF">KEY</span></span> <span style="color: #990000">(</span>id<span style="color: #990000">)</span>
+<span style="color: #990000">);</span></tt></pre></div></div>
+<div class="paragraph"><p>Following the table schema above, you would be able to write code like 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>p <span style="color: #990000">=</span> Product<span style="color: #990000">.</span>new
+p<span style="color: #990000">.</span>name <span style="color: #990000">=</span> <span style="color: #FF0000">"Some Book"</span>
+puts p<span style="color: #990000">.</span>name <span style="font-style: italic"><span style="color: #9A1900"># "Some Book"</span></span></tt></pre></div></div>
</div>
-<h4 id="_schema_conventions">2.1.2. Schema Conventions</h4>
-<div class="paragraph"><p>To take advantage of some of the magic of Rails database tables must be modeled
-to reflect the ORM decisions that Rails makes.</p></div>
+<h2 id="_convention_over_configuration_in_activerecord">6. Convention over Configuration in ActiveRecord</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>When writing applications using other programming languages or frameworks, it may be necessary to write a lot of configuration code. This is particulary true for ORM frameworks in general. However, if you follow the conventions adopted by Rails, you&#8217;ll need to write very little configuration (in some case no configuration at all) when creating ActiveRecord models. The idea is that if you configure your applications in the very same way most of the times then this should be the default way. In this cases, explicity configuration would be needed only in those cases where you can&#8217;t follow the conventions for any reason.</p></div>
+<h3 id="_naming_conventions">6.1. Naming Conventions</h3>
+<div class="paragraph"><p>By default, ActiveRecord uses some naming conventions to find out how the mapping between models and database tables should be created. Rails will pluralize your class names to find the respective database table. So, for a class <tt>Book</tt>, you should have a database table called <strong>books</strong>. The Rails pluralization mechanisms are very powerful, being capable to pluralize (and singularize) both regular and irregular words. When using class names composed of two or more words, the model class name should follow the Ruby conventions, using the camelCase form, while the table name must contain the words separated by underscores. Examples:</p></div>
+<div class="paragraph"><p>Database Table - Plural with underscores separating words i.e. (book_clubs)
+Model Class - Singular with the first letter of each word capitalized i.e. (BookClub)</p></div>
<div class="tableblock">
<table rules="all"
-frame="hsides"
+width="60%"
+frame="border"
cellspacing="0" cellpadding="4">
-<col width="160" />
-<col width="937" />
-<thead>
- <tr>
- <th align="left">
- Convention
- </th>
- <th align="left">
- </th>
- </tr>
+<col width="50%" />
+<col width="50%" />
+<thead valign="top">
+<tr>
+<th align="left">Model / Class </th>
+<th align="left">Table / Schema</th>
+</tr>
</thead>
<tbody valign="top">
- <tr>
- <td align="left">
- Foreign keys
- </td>
- <td align="left">
- These fields are named table_id i.e. (item_id, order_id)
- </td>
- </tr>
- <tr>
- <td align="left">
- Primary Key
- </td>
- <td align="left">
- Rails automatically creates a primary key column named "id" unless told otherwise.
- </td>
- </tr>
+<tr>
+<td align="left"><p class="table">Post</p></td>
+<td align="left"><p class="table">posts</p></td>
+</tr>
+<tr>
+<td align="left"><p class="table">LineItem</p></td>
+<td align="left"><p class="table">line_items</p></td>
+</tr>
+<tr>
+<td align="left"><p class="table">Deer</p></td>
+<td align="left"><p class="table">deer</p></td>
+</tr>
+<tr>
+<td align="left"><p class="table">Mouse</p></td>
+<td align="left"><p class="table">mice</p></td>
+</tr>
+<tr>
+<td align="left"><p class="table">Person</p></td>
+<td align="left"><p class="table">people</p></td>
+</tr>
</tbody>
</table>
</div>
-<h4 id="_magic_field_names">2.1.3. Magic Field Names</h4>
-<div class="paragraph"><p>When these optional fields are used in your database table definition they give the Active Record
-instance additional features.</p></div>
+<h3 id="_schema_conventions">6.2. Schema Conventions</h3>
+<div class="paragraph"><p>ActiveRecord uses naming conventions for the columns in database tables, depending on the purpose of these columns.</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+<strong>Foreign keys</strong> - These fields should be named following the pattern table_id i.e. (item_id, order_id). These are the fields that ActiveRecord will look for when you create associations between your models.
+</p>
+</li>
+<li>
+<p>
+<strong>Primary keys</strong> - By default, ActiveRecord will use a integer column named "id" as the table&#8217;s primary key. When using <a href="http://guides.rails.info/migrations.html">Rails Migrations</a> to create your tables, this column will be automaticaly created.
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>There are also some optional column names that will create additional features to ActiveRecord instances:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+<strong>created_at / created_on</strong> - ActiveRecord will store the current date and time to this field when creating the record.
+</p>
+</li>
+<li>
+<p>
+<strong>updated_at / updated_on</strong> - ActiveRecord will store the current date and times to this field when updating the record.
+</p>
+</li>
+<li>
+<p>
+<strong>lock_version</strong> - Adds <a href="http://api.rubyonrails.com/classes/ActiveRecord/Locking.html">optimistic locking</a> to a model.
+</p>
+</li>
+<li>
+<p>
+<strong>type</strong> - Specifies that the model uses <a href="http://api.rubyonrails.com/classes/ActiveRecord/Base.html">Single Table Inheritance</a>
+</p>
+</li>
+<li>
+<p>
+<strong>(table_name)_count</strong> - Used to cache the number of belonging objects on associations. For example, a <tt>comments_count</tt> column in a <tt>Post</tt> class that has many instances of <tt>Comment</tt> will cache the number of existent comments for each post.
+</p>
+</li>
+</ul></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
-<td class="content">While these column names are optional they are in fact reserved by ActiveRecord. Steer clear of reserved keywords unless you want the extra functionality. For example, "type" is a reserved keyword
-used to designate a table using Single Table Inheritance. If you are not using STI, try an analogous
-keyword like "context", that may still accurately describe the data you are modeling.</td>
+<td class="content">While these column names are optional they are in fact reserved by ActiveRecord. Steer clear of reserved keywords unless you want the extra functionality. For example, "type" is a reserved keyword used to designate a table using Single Table Inheritance. If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling.</td>
</tr></table>
</div>
<div class="tableblock">
@@ -332,11 +427,11 @@ http://www.gnu.org/software/src-highlite -->
<div class="paragraph"><p>Rails further extends this model by giving each ActiveRecord a way of describing the variety of ways records are associated with one another. We will touch on some of these associations later in the guide but I encourage readers who are interested to read the guide to ActiveRecord associations for an in-depth explanation of the variety of ways rails can model associations.
- Associations between objects controlled by meta-programming macros.</p></div>
</div>
-<h2 id="_philosophical_approaches_amp_common_conventions">3. Philosophical Approaches &amp; Common Conventions</h2>
+<h2 id="_philosophical_approaches_amp_common_conventions">7. Philosophical Approaches &amp; Common Conventions</h2>
<div class="sectionbody">
<div class="paragraph"><p>Rails has a reputation of being a zero-config framework which means that it aims to get you off the ground with as little pre-flight checking as possible. This speed benefit is achieved by following “Convention over Configuration”, which is to say that if you agree to live with the defaults then you benefit from a the inherent speed-boost. As Courtneay Gasking put it to me once “You don’t want to off-road on Rails”. ActiveRecord is no different, while it’s possible to override or subvert any of the conventions of AR, unless you have a good reason for doing so you will probably be happy with the defaults. The following is a list of the common conventions of ActiveRecord</p></div>
</div>
-<h2 id="_activerecord_magic">4. ActiveRecord Magic</h2>
+<h2 id="_activerecord_magic">8. ActiveRecord Magic</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
@@ -351,7 +446,7 @@ updates
</li>
</ul></div>
</div>
-<h2 id="_how_activerecord_maps_your_database">5. How ActiveRecord Maps your Database.</h2>
+<h2 id="_how_activerecord_maps_your_database">9. How ActiveRecord Maps your Database.</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
@@ -366,10 +461,10 @@ overriding conventions
</li>
</ul></div>
</div>
-<h2 id="_growing_your_database_relationships_naturally">6. Growing Your Database Relationships Naturally</h2>
+<h2 id="_growing_your_database_relationships_naturally">10. Growing Your Database Relationships Naturally</h2>
<div class="sectionbody">
</div>
-<h2 id="_attributes">7. Attributes</h2>
+<h2 id="_attributes">11. Attributes</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
@@ -391,7 +486,7 @@ dirty records
</li>
</ul></div>
</div>
-<h2 id="_validations_amp_callbacks">8. Validations &amp; Callbacks</h2>
+<h2 id="_validations_amp_callbacks">12. Validations &amp; Callbacks</h2>
<div class="sectionbody">
<div class="paragraph"><p>see the Validations &amp; Callbacks guide for more info.</p></div>
</div>
diff --git a/railties/doc/guides/html/creating_plugins.html b/railties/doc/guides/html/creating_plugins.html
index 3347f77228..1c512519f9 100644
--- a/railties/doc/guides/html/creating_plugins.html
+++ b/railties/doc/guides/html/creating_plugins.html
@@ -768,7 +768,7 @@ ActiveRecord<span style="color: #990000">::</span>Base<span style="color: #99000
| `-- yaffle.rb</tt></pre>
</div></div>
<div class="paragraph"><p>As always, start with a test:</p></div>
-<div class="paragraph"><p><strong>vendor/plugins/yaffle/yaffle/woodpecker_test.rb:</strong></p></div>
+<div class="paragraph"><p><strong>vendor/plugins/yaffle/test/woodpecker_test.rb:</strong></p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1212,7 +1212,7 @@ Rails<span style="color: #990000">::</span>Generator<span style="color: #990000"
Rails<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>Commands<span style="color: #990000">::</span>Destroy<span style="color: #990000">.</span>send <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">,</span> Yaffle<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>Commands<span style="color: #990000">::</span>Destroy
Rails<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>Commands<span style="color: #990000">::</span>List<span style="color: #990000">.</span>send <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">,</span> Yaffle<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>Commands<span style="color: #990000">::</span>List
Rails<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>Commands<span style="color: #990000">::</span>Update<span style="color: #990000">.</span>send <span style="color: #990000">:</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">,</span> Yaffle<span style="color: #990000">::</span>Generator<span style="color: #990000">::</span>Commands<span style="color: #990000">::</span>Update</tt></pre></div></div>
-<div class="paragraph"><p><strong>vendor/plugins/yaffle/generators/yaffle/yaffle_route_generator.rb</strong></p></div>
+<div class="paragraph"><p><strong>vendor/plugins/yaffle/generators/yaffle_route/yaffle_route_generator.rb</strong></p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1266,25 +1266,7 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
<div class="paragraph"><p>Here are a few possibilities for how to allow developers to use your plugin migrations:</p></div>
<h3 id="_create_a_custom_rake_task">11.1. Create a custom rake task</h3>
-<div class="paragraph"><p><strong>vendor/plugins/yaffle/lib/db/migrate/20081116181115_create_birdhouses.rb:</strong></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> CreateBirdhouses <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Migration
- <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>up
- create_table <span style="color: #990000">:</span>birdhouses<span style="color: #990000">,</span> <span style="color: #990000">:</span>force <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">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
- t<span style="color: #990000">.</span>timestamps
- <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">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>birdhouses
- <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="paragraph"><p><strong>vendor/plugins/yaffle/tasks/yaffle.rake:</strong></p></div>
+<div class="paragraph"><p><strong>vendor/plugins/yaffle/tasks/yaffle_tasks.rake:</strong></p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1406,7 +1388,7 @@ http://www.gnu.org/software/src-highlite -->
</tr></table>
</div>
<div class="paragraph"><p>After running the test with <em>rake</em> you can make it pass with:</p></div>
-<div class="paragraph"><p><strong>vendor/plugins/yaffle/generators/yaffle/yaffle_generator.rb</strong></p></div>
+<div class="paragraph"><p><strong>vendor/plugins/yaffle/generators/yaffle_migration/yaffle_migration_generator.rb</strong></p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1463,9 +1445,9 @@ http://www.gnu.org/software/src-highlite -->
</div>
<h2 id="_rake_tasks">12. Rake tasks</h2>
<div class="sectionbody">
-<div class="paragraph"><p>When you created the plugin with the built-in rails generator, it generated a rake file for you in <em>vendor/plugins/yaffle/tasks/yaffle.rake</em>. Any rake task you add here will be available to the app.</p></div>
+<div class="paragraph"><p>When you created the plugin with the built-in rails generator, it generated a rake file for you in <em>vendor/plugins/yaffle/tasks/yaffle_tasks.rake</em>. Any rake task you add here will be available to the app.</p></div>
<div class="paragraph"><p>Many plugin authors put all of their rake tasks into a common namespace that is the same as the plugin, like so:</p></div>
-<div class="paragraph"><p><strong>vendor/plugins/yaffle/tasks/yaffle.rake</strong></p></div>
+<div class="paragraph"><p><strong>vendor/plugins/yaffle/tasks/yaffle_tasks.rake</strong></p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1577,7 +1559,7 @@ Warning, gotchas or tips that might help save users time
</li>
<li>
<p>
-<a href="http://nubyonrails.com/articles/2006/05/09/the-complete-guide-to-rails-plugins-part-ii">http://nubyonrails.com/articles/2006/05/09/the-complete-guide-to-rails-plugins-part-ii</a>
+<a href="http://nubyonrails.com/articles/the-complete-guide-to-rails-plugins-part-ii">http://nubyonrails.com/articles/the-complete-guide-to-rails-plugins-part-ii</a>
</p>
</li>
<li>
diff --git a/railties/doc/guides/html/form_helpers.html b/railties/doc/guides/html/form_helpers.html
index 54155cddb6..2693f29a9a 100644
--- a/railties/doc/guides/html/form_helpers.html
+++ b/railties/doc/guides/html/form_helpers.html
@@ -34,9 +34,9 @@
<a href="#_dealing_with_basic_forms">Dealing With Basic Forms</a>
<ul>
- <li><a href="#_generic_search_form">Generic search form</a></li>
+ <li><a href="#_a_generic_search_form">A Generic search form</a></li>
- <li><a href="#_multiple_hashes_in_form_helper_attributes">Multiple hashes in form helper attributes</a></li>
+ <li><a href="#_multiple_hashes_in_form_helper_calls">Multiple hashes in form helper calls</a></li>
<li><a href="#_helpers_for_generating_form_elements">Helpers for generating form elements</a></li>
@@ -60,7 +60,7 @@
<a href="#_making_select_boxes_with_ease">Making select boxes with ease</a>
<ul>
- <li><a href="#_the_select_tag_and_options">The select tag and options</a></li>
+ <li><a href="#_the_select_and_options_tag">The select and options tag</a></li>
<li><a href="#_select_boxes_for_dealing_with_models">Select boxes for dealing with models</a></li>
@@ -80,6 +80,8 @@
<li><a href="#_common_options">Common options</a></li>
+ <li><a href="#_individual_components">Individual components</a></li>
+
</ul>
</li>
<li>
@@ -125,22 +127,32 @@
<div class="ulist"><ul>
<li>
<p>
-Create search forms and similar kind of generic forms not representing any specific model in your application;
+Create search forms and similar kind of generic forms not representing any specific model in your application
+</p>
+</li>
+<li>
+<p>
+Make model-centric forms for creation and editing of specific database records
+</p>
+</li>
+<li>
+<p>
+Generate select boxes from multiple types of data
</p>
</li>
<li>
<p>
-Make model-centric forms for creation and editing of specific database records;
+Understand the date and time helpers Rails provides
</p>
</li>
<li>
<p>
-Generate select boxes from multiple types of data;
+Learn what makes a file upload form different
</p>
</li>
<li>
<p>
-Learn what makes a file upload form different;
+Find out where to look for complex forms
</p>
</li>
</ul></div>
@@ -163,7 +175,7 @@ Learn what makes a file upload form different;
Form contents
&lt;% end %&gt;</tt></pre>
</div></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="paragraph"><p>When called without arguments like this, it creates a form element that has the current page as its action and "post" as its method (some line breaks added for readability):</p></div>
<div class="listingblock">
<div class="title">Sample output from <tt>form_tag</tt></div>
<div class="content">
@@ -174,7 +186,7 @@ Learn what makes a file upload form different;
Form contents
&lt;/form&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>If you carefully observe this output, you can see that the helper generated something you 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="paragraph"><p>If you carefully observe this output, you can see that the helper generated something you 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 whose action is not "get" (provided that this security feature is enabled). You can read more about this in the <a href="./security.html#_cross_site_reference_forgery_csrf">Ruby On Rails Security Guide</a>.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -183,7 +195,7 @@ Learn what makes a file upload form different;
<td class="content">Throughout this guide, this <tt>div</tt> with the hidden input will be stripped away to have clearer code samples.</td>
</tr></table>
</div>
-<h3 id="_generic_search_form">1.1. Generic search form</h3>
+<h3 id="_a_generic_search_form">1.1. A Generic search form</h3>
<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 arabic"><ol class="arabic">
<li>
@@ -212,10 +224,10 @@ a submit element.
<td class="icon">
<img src="./images/icons/important.png" alt="Important" />
</td>
-<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 others.</td>
+<td class="content">Always use "GET" as the method for search forms. This allows users are able to bookmark a specific search and get back to it, more generally Rails encourages you to use the right HTTP verb for an action.</td>
</tr></table>
</div>
-<div class="paragraph"><p>To create that, you 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 this form you 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">A basic search form</div>
<div class="content">
@@ -258,8 +270,8 @@ a submit element.
<td class="content">For every form input, an ID attribute is generated from its name ("q" in the example). These IDs can be very useful for CSS styling or manipulation of form controls with JavaScript.</td>
</tr></table>
</div>
-<h3 id="_multiple_hashes_in_form_helper_attributes">1.2. Multiple hashes in form helper attributes</h3>
-<div class="paragraph"><p>By now you&#8217;ve seen that the <tt>form_tag</tt> helper accepts 2 arguments: the path for the action and an options hash. This hash specifies the method of form submission and HTML options such as the form element&#8217;s class.</p></div>
+<h3 id="_multiple_hashes_in_form_helper_calls">1.2. Multiple hashes in form helper calls</h3>
+<div class="paragraph"><p>By now you&#8217;ve seen that the <tt>form_tag</tt> helper accepts 2 arguments: the path for the action and an options hash. This hash specifies the method of form submission and HTML options such as the form element&#8217;s class.</p></div>
<div class="paragraph"><p>As with the &#8216;link_to` helper, the path argument doesn&#8217;t have to be given a string. It can be a hash of URL parameters that Rails&#8217; routing mechanism will turn into a valid URL. Still, you cannot simply write this:</p></div>
<div class="listingblock">
<div class="title">A bad way to pass multiple hashes as method arguments</div>
@@ -284,7 +296,7 @@ a submit element.
</tr></table>
</div>
<h3 id="_helpers_for_generating_form_elements">1.3. Helpers for generating form elements</h3>
-<div class="paragraph"><p>Rails provides a series of helpers for generating form elements such as checkboxes, text fields, radio buttons and so. These basic helpers, with names ending in _tag such as <tt>text_field_tag</tt>, <tt>check_box_tag</tt> just generate a single <tt>&lt;input&gt;</tt> element. The first parameter to these is always the name of the input. This is the name under which value will appear in the <tt>params</tt> hash in the controller. For example if the form contains</p></div>
+<div class="paragraph"><p>Rails provides a series of helpers for generating form elements such as checkboxes, text fields, radio buttons and so. These basic helpers, with names ending in _tag such as <tt>text_field_tag</tt>, <tt>check_box_tag</tt> just generate a single <tt>&lt;input&gt;</tt> element. The first parameter to these is always the name of the input. In the controller, this name will be the key in the <tt>params</tt> hash used to get the value entered by the user. For example if the form contains</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= text_field_tag(:query) %&gt;</tt></pre>
@@ -294,7 +306,7 @@ a submit element.
<div class="content">
<pre><tt>params[:query]</tt></pre>
</div></div>
-<div class="paragraph"><p>to retrieve the value entered by the user. When naming inputs be aware that Rails uses certain conventions that control whether values appear at the top level of the params hash, inside an array or a nested hash and so on. You can read more about them in the <a href="#parameter_names">parameter names</a> section. For details on the precise usage of these helpers, please refer to the <a href="http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html">API documentation</a>.</p></div>
+<div class="paragraph"><p>to retrieve the value entered by the user. When naming inputs be aware that Rails uses certain conventions that control whether values are at the top level of the <tt>params</tt> hash, inside an array or a nested hash and so on. You can read more about them in the <a href="#parameter_names">parameter names</a> section. For details on the precise usage of these helpers, please refer to the <a href="http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html">API documentation</a>.</p></div>
<h4 id="_checkboxes">1.3.1. Checkboxes</h4>
<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">
@@ -311,7 +323,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="paragraph"><p>The second parameter to <tt>check_box_tag</tt> is the value of the input. This is the value that will be submitted by the browser if the checkbox is ticked (i.e. the value that will be present in the params hash). With the above form you would check the value of <tt>params[:pet_dog]</tt> and <tt>params[:pet_cat]</tt> to see which pets the user owns.</p></div>
+<div class="paragraph"><p>The second parameter to <tt>check_box_tag</tt> is the value of the input. This is the value that will be submitted by the browser if the checkbox is ticked (i.e. the value that will be present in the <tt>params</tt> hash). With the above form you would check the value of <tt>params[:pet_dog]</tt> and <tt>params[:pet_cat]</tt> to see which pets the user owns.</p></div>
<h4 id="_radio_buttons">1.3.2. Radio buttons</h4>
<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">
@@ -328,7 +340,7 @@ output:
&lt;input id="age_adult" name="age" type="radio" value="adult" /&gt;
&lt;label for="age_adult"&gt;I'm over 21&lt;/label&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>As with <tt>check_box_tag</tt> the second parameter to <tt>radio_button_tag</tt> is the value of the input. Because these two radio buttons share the same name (age) the user will only be able to select one and <tt>params[:age]</tt> will contain either <tt>child</tt> or <tt>adult</tt>.</p></div>
+<div class="paragraph"><p>As with <tt>check_box_tag</tt> the second parameter to <tt>radio_button_tag</tt> is the value of the input. Because these two radio buttons share the same name (age) the user will only be able to select one and <tt>params[:age]</tt> will contain either "child" or "adult".</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -364,7 +376,7 @@ output:
<h2 id="_dealing_with_model_objects">2. Dealing With Model Objects</h2>
<div class="sectionbody">
<h3 id="_model_object_helpers">2.1. Model object helpers</h3>
-<div class="paragraph"><p>A particularly common task for a form is editing or creating a model object. While the <tt>*_tag</tt> helpers could certainly be used for this task they are somewhat verbose as for each tag you would have to ensure the correct parameter name is used and set the default value of the input appropriately. Rails provides helpers tailored to this task. These helpers lack the _tag suffix, for example <tt>text_field</tt>, <tt>text_area</tt>.</p></div>
+<div class="paragraph"><p>A particularly common task for a form is editing or creating a model object. While the <tt>*_tag</tt> helpers can certainly be used for this task they are somewhat verbose as for each tag you would have to ensure the correct parameter name is used and set the default value of the input appropriately. Rails provides helpers tailored to this task. These helpers lack the _tag suffix, for example <tt>text_field</tt>, <tt>text_area</tt>.</p></div>
<div class="paragraph"><p>For these helpers the first argument is the name of an instance variable and the second is the name of a method (usually an attribute) to call on that object. Rails will set the value of the input control to the return value of that method for the object and set an appropriate input name. If your controller has defined <tt>@person</tt> and that person&#8217;s name is Henry then a form containing:</p></div>
<div class="listingblock">
<div class="content">
@@ -375,7 +387,7 @@ output:
<div class="content">
<pre><tt>&lt;input id="person_name" name="person[name]" type="text" value="Henry"/&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>Upon form submission the value entered by the user will be stored in <tt>params[:person][:name]</tt>. The <tt>params[:person]</tt> hash is suitable for passing to <tt>Person.new</tt> or, if <tt>@person</tt> is an instance of Person, <tt>@person.update_attributes</tt>.</p></div>
+<div class="paragraph"><p>Upon form submission the value entered by the user will be stored in <tt>params[:person][:name]</tt>. The <tt>params[:person]</tt> hash is suitable for passing to <tt>Person.new</tt> or, if <tt>@person</tt> is an instance of Person, <tt>@person.update_attributes</tt>. While the name of an attribute is the most common second parameter to these helpers this is not compulsory. In the example above, as long as person objects have a <tt>name</tt> and a <tt>name=</tt> method Rails will be happy.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -439,12 +451,12 @@ 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="paragraph"><p>The name passed to <tt>form_for</tt> controls where in the params hash the form values will appear. Here the name is <tt>article</tt> and so all the inputs have names of the form <tt>article[attribute_name]</tt>. Accordingly, in the <tt>create</tt> action <tt>params[:article]</tt> will be a hash with keys <tt>:title</tt> and <tt>:body</tt>. You can read more about the significance of input names in the <a href="#parameter_names">parameter names</a> section.</p></div>
+<div class="paragraph"><p>The name passed to <tt>form_for</tt> controls the key used in <tt>params</tt> to access the form&#8217;s values. Here the name is <tt>article</tt> and so all the inputs have names of the form <tt>article[attribute_name]</tt>. Accordingly, in the <tt>create</tt> action <tt>params[:article]</tt> will be a hash with keys <tt>:title</tt> and <tt>:body</tt>. You can read more about the significance of input names in the <a href="#parameter_names">parameter names</a> section.</p></div>
<div class="paragraph"><p>The helper methods called on the form builder are identical to the model object helpers except that it is not necessary to specify which object is being edited since this is already managed by the form builder.</p></div>
-<div class="paragraph"><p>You can create a similar binding without actually creating <tt>&lt;form&gt;</tt> tags with the <tt>fields_for</tt> helper. This is useful for editing additional model objects with the same form. For example if you had a Person model with an associated ContactDetail model you could create a form for editing both like so:</p></div>
+<div class="paragraph"><p>You can create a similar binding without actually creating <tt>&lt;form&gt;</tt> tags with the <tt>fields_for</tt> helper. This is useful for editing additional model objects with the same form. For example if you had a Person model with an associated ContactDetail model you could create a form for creating both like so:</p></div>
<div class="listingblock">
<div class="content">
-<pre><tt>&lt;% form_for @person do |person_form| %&gt;
+<pre><tt>&lt;% form_for :person, @person, :url =&gt; { :action =&gt; "create" } do |person_form| %&gt;
&lt;%= person_form.text_field :name %&gt;
&lt;% fields_for @person.contact_detail do |contact_details_form| %&gt;
&lt;%= contact_details_form.text_field :phone_number %&gt;
@@ -454,14 +466,14 @@ Methods to create form controls are called <strong>on</strong> the form builder
<div class="paragraph"><p>which produces the following output:</p></div>
<div class="listingblock">
<div class="content">
-<pre><tt>&lt;form action="/people/1" class="edit_person" id="edit_person_1" method="post"&gt;
+<pre><tt>&lt;form action="/people/create" class="new_person" id="new_person" method="post"&gt;
&lt;input id="person_name" name="person[name]" size="30" type="text" /&gt;
&lt;input id="contact_detail_phone_number" name="contact_detail[phone_number]" size="30" type="text" /&gt;
&lt;/form&gt;</tt></pre>
</div></div>
<div class="paragraph"><p>The object yielded by <tt>fields_for</tt> is a form builder like the one yielded by <tt>form_for</tt> (in fact <tt>form_for</tt> calls <tt>fields_for</tt> internally).</p></div>
<h3 id="_relying_on_record_identification">2.3. Relying on record identification</h3>
-<div class="paragraph"><p>The Article model is directly available to users of our application, so&#8201;&#8212;&#8201;following the best practices for developing with Rails&#8201;&#8212;&#8201;you should declare it <strong>a resource</strong>.</p></div>
+<div class="paragraph"><p>The Article model is directly available to users of the application, so&#8201;&#8212;&#8201;following the best practices for developing with Rails&#8201;&#8212;&#8201;you should declare it <strong>a resource</strong>.</p></div>
<div class="paragraph"><p>When dealing with RESTful resources, calls to <tt>form_for</tt> can get significantly easier if you rely on <strong>record identification</strong>. In short, you can just pass the model instance and have Rails figure out model name and the rest:</p></div>
<div class="listingblock">
<div class="content">
@@ -478,7 +490,7 @@ form_for(:article, @article, :url =&gt; article_path(@article), :method =&gt; "p
form_for(@article)</tt></pre>
</div></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>. It also selects the correct path to submit to and the name based on the class of the object.</p></div>
-<div class="paragraph"><p>Rails will also automatically set the class and id of the form appropriately: a form creating an article would have id and class <tt>new_article</tt>. If you were editing the article with id 23 the class would be set to <tt>edit_article</tt> and the id to <tt>edit_article_23</tt>. The attributes will be omitted or brevity in the rest of this guide.</p></div>
+<div class="paragraph"><p>Rails will also automatically set the <tt>class</tt> and <tt>id</tt> of the form appropriately: a form creating an article would have <tt>id</tt> and <tt>class</tt> <tt>new_article</tt>. If you were editing the article with id 23 the <tt>class</tt> would be set to <tt>edit_article</tt> and the id to <tt>edit_article_23</tt>. These attributes will be omitted for brevity in the rest of this guide.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -500,7 +512,7 @@ form_for(@article)</tt></pre>
</div></div>
<div class="paragraph"><p>For more information on Rails' routing system and the associated conventions, please see the <a href="./routing_outside_in.html">routing guide</a>.</p></div>
<h3 id="_how_do_forms_with_put_or_delete_methods_work">2.4. How do forms with PUT or DELETE methods work?</h3>
-<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 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.</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 desired method:</p></div>
<div class="listingblock">
<div class="content">
@@ -515,7 +527,7 @@ output:
&lt;/div&gt;
...</tt></pre>
</div></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 class="paragraph"><p>When parsing POSTed data, Rails will take into account the special <tt>_method</tt> parameter and acts as if the HTTP method was the one specified inside it ("PUT" in this example).</p></div>
</div>
<h2 id="_making_select_boxes_with_ease">3. Making select boxes with ease</h2>
<div class="sectionbody">
@@ -524,71 +536,70 @@ output:
<div class="listingblock">
<div class="content">
<pre><tt>&lt;select name="city_id" id="city_id"&gt;
- &lt;option value="1"&gt;Lisabon&lt;/option&gt;
+ &lt;option value="1"&gt;Lisbon&lt;/option&gt;
&lt;option value="2"&gt;Madrid&lt;/option&gt;
...
&lt;option value="12"&gt;Berlin&lt;/option&gt;
&lt;/select&gt;</tt></pre>
</div></div>
<div class="paragraph"><p>Here you have a list of cities whose names are presented to the user. Internally the application only wants to handle their IDs so they are used as the options' value attribute. 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>
+<h3 id="_the_select_and_options_tag">3.1. The select and options tag</h3>
<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>
+<pre><tt>&lt;%= select_tag(:city_id, '&lt;option value="1"&gt;Lisbon&lt;/option&gt;...') %&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>This is a start, but it doesn&#8217;t dynamically create our option tags. You 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 the option tags. You 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;
+<pre><tt>&lt;%= options_for_select([['Lisbon', 1], ['Madrid', 2], ...]) %&gt;
output:
-&lt;option value="1"&gt;Lisabon&lt;/option&gt;
+&lt;option value="1"&gt;Lisbon&lt;/option&gt;
&lt;option value="2"&gt;Madrid&lt;/option&gt;
...</tt></pre>
</div></div>
-<div class="paragraph"><p>For input data you use a nested array where each element has two elements: option text (city name) and option value (city id). The option value is what will get submitted to your controller. It is often true that the option value is the id of a corresponding database object but this does not have to be the case.</p></div>
+<div class="paragraph"><p>The first argument to <tt>options_for_select</tt> is a nested array where each element has two elements: option text (city name) and option value (city id). The option value is what will be submitted to your controller. Often this will be the id of a corresponding database object but this does not have to be the case.</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="paragraph"><p>Sometimes, depending on an application&#8217;s needs, you 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><tt>options_for_select</tt> allows you to pre-select an option by passing its value.</p></div>
<div class="listingblock">
<div class="content">
-<pre><tt>&lt;%= options_for_select([['Lisabon', 1], ['Madrid', 2], ...], 2) %&gt;
+<pre><tt>&lt;%= options_for_select([['Lisbon', 1], ['Madrid', 2], ...], 2) %&gt;
output:
-&lt;option value="1"&gt;Lisabon&lt;/option&gt;
+&lt;option value="1"&gt;Lisbon&lt;/option&gt;
&lt;option value="2" selected="selected"&gt;Madrid&lt;/option&gt;
...</tt></pre>
</div></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>
+<div class="paragraph"><p>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>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip" />
</td>
<td class="content">
-<div class="paragraph"><p>The second argument to <tt>options_for_select</tt> must be exactly equal to the desired internal value. In particular if the internal value is the integer 2 you cannot pass "2" to <tt>options_for_select</tt>&#8201;&#8212;&#8201;you must pass 2. Be aware of values extracted from the params hash as they are all strings.</p></div>
+<div class="paragraph"><p>The second argument to <tt>options_for_select</tt> must be exactly equal to the desired internal value. In particular if the value is the integer 2 you cannot pass "2" to <tt>options_for_select</tt>&#8201;&#8212;&#8201;you must pass 2. Be aware of values extracted from the <tt>params</tt> hash as they are all strings.</p></div>
</td>
</tr></table>
</div>
<h3 id="_select_boxes_for_dealing_with_models">3.2. Select boxes for dealing with models</h3>
-<div class="paragraph"><p>Until now you&#8217;ve seen 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 you 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 you drop the <tt>_tag</tt> suffix from <tt>select_tag</tt>.</p></div>
+<div class="paragraph"><p>In most cases form controls will be tied to a specific database model and as you might expect Rails provides helpers tailored for that purpose. Consistent with other form helpers, when dealing with models you drop the <tt>_tag</tt> suffix from <tt>select_tag</tt>:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt># controller:
@person = Person.new(:city_id =&gt; 2)
# view:
-&lt;%= select(:person, :city_id, [['Lisabon', 1], ['Madrid', 2], ...]) %&gt;</tt></pre>
+&lt;%= select(:person, :city_id, [['Lisbon', 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 you pass to <tt>options_for_select</tt>. One advantage here is that you 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 you by reading from the <tt>@person.city_id</tt> attribute.</p></div>
-<div class="paragraph"><p>As before, if you 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="paragraph"><p>As with other helpers, if you 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
@@ -600,25 +611,22 @@ output:
<img src="./images/icons/warning.png" alt="Warning" />
</td>
<td class="content">
-<div class="paragraph"><p>If you are using <tt>select</tt> (or similar helpers such as <tt>collection_select</tt>, <tt>select_tag</tt>) to set a <tt>belongs_to</tt> association you must pass the name of the foreign key (in the example above <tt>city_id</tt>), not the name of association itself. If you specify <tt>city</tt> instead of `city_id Active Record will raise an error along the lines of</p></div>
+<div class="paragraph"><p>If you are using <tt>select</tt> (or similar helpers such as <tt>collection_select</tt>, <tt>select_tag</tt>) to set a <tt>belongs_to</tt> association you must pass the name of the foreign key (in the example above <tt>city_id</tt>), not the name of association itself.</p></div>
+<div class="paragraph"><p>If you specify <tt>city</tt> instead of <tt>city_id</tt> Active Record will raise an error along the lines of</p></div>
<div class="listingblock">
<div class="content">
-<pre><tt>ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got Fixnum(#1138750)</tt></pre>
+<pre><tt>ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750)</tt></pre>
</div></div>
-<div class="paragraph"><p>when you pass the params hash to <tt>Person.new</tt> or <tt>update_attributes</tt>. Another way of looking at this is that form helpers only edit attributes.</p></div>
+<div class="paragraph"><p>when you pass the <tt>params</tt> hash to <tt>Person.new</tt> or <tt>update_attributes</tt>. Another way of looking at this is that form helpers only edit attributes.</p></div>
+<div class="paragraph"><p>You should also be aware of the potential security ramifications of allowing users to edit foreign keys directly. You may wish to consider the use of <tt>attr_protected</tt> and <tt>attr_accessible</tt>. For further details on this, see the <a href="security.html#_mass_assignment">Ruby On Rails Security Guide</a>.</p></div>
</td>
</tr></table>
</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 you 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="paragraph"><p>Generating options tags with <tt>options_for_select</tt> requires that you create an array containing the text and value for each option. But what if you had a City model (perhaps an Active Record one) and you 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;%= options_for_select([['Lisabon', 1], ['Madrid', 2], ...]) %&gt;</tt></pre>
-</div></div>
-<div class="paragraph"><p>But what if you had a <strong>City</strong> model (perhaps an Active Record one) and you 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;
+<pre><tt>&lt;% cities_array = City.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 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>
@@ -626,17 +634,27 @@ output:
<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. To generate a working select box you would need to use it in conjunction with <tt>select_tag</tt>, just as you would with <tt>options_for_select</tt>. A method to go along with it is <tt>collection_select</tt>:</p></div>
+<div class="paragraph"><p>As the name implies, this only generates option tags. To generate a working select box you would need to use it in conjunction with <tt>select_tag</tt>, just as you would with <tt>options_for_select</tt>. When working with model objects, just as <tt>select</tt> combines <tt>select_tag</tt> and <tt>options_for_select</tt>, <tt>collection_select</tt> combines <tt>select_tag</tt> with <tt>options_from_collection_for_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> is to <tt>collection_select</tt> what <tt>options_for_select</tt> is to <tt>select</tt>.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="./images/icons/note.png" alt="Note" />
+</td>
+<td class="content">
+<div class="paragraph"><p>Pairs passed to <tt>options_for_select</tt> should have the name first and the id second, however with <tt>options_from_collection_for_select</tt> the first argument is the value method and the second the text method.</p></div>
+</td>
+</tr></table>
+</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, you 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 you can simply use the <tt>time_zone_select</tt> helper that already wraps this:</p></div>
+<div class="paragraph"><p>To leverage time zone support in Rails, you have to ask your 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 you 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>
+<pre><tt>&lt;%= time_zone_select(:person, :time_zone) %&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>Rails <em>used</em> to have a <tt>country_select</tt> helper for choosing countries but this has been extracted to the <a href="http://github.com/rails/country_select/tree/master">country_select plugin</a>. When using this do be aware that the exclusion or inclusion of certain names from the list can be somewhat controversial (and was the reason this functionality was extracted from rails).</p></div>
@@ -647,55 +665,55 @@ output:
<div class="olist arabic"><ol class="arabic">
<li>
<p>
-Unlike other attributes you might typically have, dates and times are not representable by a single input element. Instead you have several, one for each component (year, month, day etc...). So in particular, there is no single value in your params hash with your date or time.
+Dates and times are not representable by a single input element. Instead you have several, one for each component (year, month, day etc.) and so there is no single value in your <tt>params</tt> hash with your date or time.
</p>
</li>
<li>
<p>
-Other helpers use the _tag suffix to indicate whether a helper is a barebones helper or one that operates on model objects. With dates and times, <tt>select\_date</tt>, <tt>select\_time</tt> and <tt>select_datetime</tt> are the barebones helpers, <tt>date_select</tt>, <tt>time_select</tt> and <tt>datetime_select</tt> are the equivalent model object helpers
+Other helpers use the _tag suffix to indicate whether a helper is a barebones helper or one that operates on model objects. With dates and times, <tt>select_date</tt>, <tt>select_time</tt> and <tt>select_datetime</tt> are the barebones helpers, <tt>date_select</tt>, <tt>time_select</tt> and <tt>datetime_select</tt> are the equivalent model object helpers.
</p>
</li>
</ol></div>
-<div class="paragraph"><p>Both of these families of helpers will create a series of select boxes for the different components (year, month, day etc...).</p></div>
+<div class="paragraph"><p>Both of these families of helpers will create a series of select boxes for the different components (year, month, day etc.).</p></div>
<h3 id="_barebones_helpers">4.1. Barebones helpers</h3>
<div class="paragraph"><p>The <tt>select_*</tt> family of helpers take as their first argument an instance of Date, Time or DateTime that is used as the currently selected value. You may omit this parameter, in which case the current date is used. For example</p></div>
<div class="listingblock">
<div class="content">
-<pre><tt>&lt;%= select_date Date::today, :prefix =&gt; :start_date %&gt;</tt></pre>
+<pre><tt>&lt;%= select_date Date.today, :prefix =&gt; :start_date %&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>outputs (with the actual option values omitted for brevity)</p></div>
+<div class="paragraph"><p>outputs (with actual option values omitted for brevity)</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;select id="start_date_year" name="start_date[year]"&gt; ... &lt;/select&gt;
&lt;select id="start_date_month" name="start_date[month]"&gt; ... &lt;/select&gt;
&lt;select id="start_date_day" name="start_date[day]"&gt; ... &lt;/select&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>The above inputs would result in <tt>params[:start_date]</tt> being a hash with keys :year, :month, :day. To get an actual Time or Date object you would have to extract these values and pass them to the appropriate constructor, for example</p></div>
+<div class="paragraph"><p>The above inputs would result in <tt>params[:start_date]</tt> being a hash with keys <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>. To get an actual Time or Date object you would have to extract these values and pass them to the appropriate constructor, for example</p></div>
<div class="listingblock">
<div class="content">
-<pre><tt>Date::civil(params[:start_date][:year].to_i, params[:start_date][:month].to_i, params[:start_date][:day].to_i)</tt></pre>
+<pre><tt>Date.civil(params[:start_date][:year].to_i, params[:start_date][:month].to_i, params[:start_date][:day].to_i)</tt></pre>
</div></div>
-<div class="paragraph"><p>The :prefix option controls where in the params hash the date components will be placed. Here it was set to <tt>start_date</tt>, if omitted it will default to <tt>date</tt>.</p></div>
+<div class="paragraph"><p>The <tt>:prefix</tt> option is the key used to retrieve the hash of date components from the <tt>params</tt> hash. Here it was set to <tt>start_date</tt>, if omitted it will default to <tt>date</tt>.</p></div>
<h3 id="_model_object_helpers_2">4.2. Model object helpers</h3>
-<div class="paragraph"><p><tt>select_date</tt> does not work well with forms that update or create Active Record objects as Active Record expects each element of the params hash to correspond to one attribute.
-The model object helpers for dates and times submit parameters with special names. When Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type. For example</p></div>
+<div class="paragraph"><p><tt>select_date</tt> does not work well with forms that update or create Active Record objects as Active Record expects each element of the <tt>params</tt> hash to correspond to one attribute.
+The model object helpers for dates and times submit parameters with special names, when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type. For example:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;%= date_select :person, :birth_date %&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>outputs (with the actual option values omitted for brevity)</p></div>
+<div class="paragraph"><p>outputs (with actual option values omitted for brevity)</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;select id="person_birth_date_1i" name="person[birth_date(1i)]"&gt; ... &lt;/select&gt;
&lt;select id="person_birth_date_2i" name="person[birth_date(2i)]"&gt; ... &lt;/select&gt;
&lt;select id="person_birth_date_3i" name="person[birth_date(3i)]"&gt; ... &lt;/select&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>which results in a params hash like</p></div>
+<div class="paragraph"><p>which results in a <tt>params</tt> hash like</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>{:person =&gt; {'birth_date(1i)' =&gt; '2008', 'birth_date(2i)' =&gt; '11', 'birth_date(3i)' =&gt; '22'}}</tt></pre>
</div></div>
-<div class="paragraph"><p>When this is passed to <tt>Person.new</tt>, Active Record spots that these parameters should all be used to construct the <tt>birth_date</tt> attribute and uses the suffixed information to determine in which order it should pass these parameters to functions such as <tt>Date::civil</tt>.</p></div>
+<div class="paragraph"><p>When this is passed to <tt>Person.new</tt> (or <tt>update_attributes</tt>), Active Record spots that these parameters should all be used to construct the <tt>birth_date</tt> attribute and uses the suffixed information to determine in which order it should pass these parameters to functions such as <tt>Date.civil</tt>.</p></div>
<h3 id="_common_options">4.3. Common options</h3>
<div class="paragraph"><p>Both families of helpers use the same core set of functions to generate the individual select tags and so both accept largely the same options. In particular, by default Rails will generate year options 5 years either side of the current year. If this is not an appropriate range, the <tt>:start_year</tt> and <tt>:end_year</tt> options override this. For an exhaustive list of the available options, refer to the <a href="http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html">API documentation</a>.</p></div>
<div class="paragraph"><p>As a rule of thumb you should be using <tt>date_select</tt> when working with model objects and <tt>select_date</tt> in others cases, such as a search form which filters results by date.</p></div>
@@ -707,10 +725,19 @@ The model object helpers for dates and times submit parameters with special name
<td class="content">In many cases the built in date pickers are clumsy as they do not aid the user in working out the relationship between the date and the day of the week.</td>
</tr></table>
</div>
+<h3 id="_individual_components">4.4. Individual components</h3>
+<div class="paragraph"><p>Occasionally you need to display just a single date component such as a year or a month. Rails provides a series of helpers for this, one for each component <tt>select_year</tt>, <tt>select_month</tt>, <tt>select_day</tt>, <tt>select_hour</tt>, <tt>select_minute</tt>, <tt>select_second</tt>. These helpers are fairly straightforward. By default they will generate a input named after the time component (for example "year" for <tt>select_year</tt>, "month" for <tt>select_month</tt> etc.) although this can be overriden with the <tt>:field_name</tt> option. The <tt>:prefix</tt> option works in the same way that it does for <tt>select_date</tt> and <tt>select_time</tt> and has the same default value.</p></div>
+<div class="paragraph"><p>The first parameter specifies which value should be selected and can either be an instance of a Date, Time or DateTime, in which case the relevant component will be extracted, or a numerical value. For example</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>&lt;%= select_year(2009) %&gt;
+&lt;%= select_year(Time.now) %&gt;</tt></pre>
+</div></div>
+<div class="paragraph"><p>will produce the same output if the current year is 2009 and the value chosen by the user can be retrieved by <tt>params[:date][:year]</tt>.</p></div>
</div>
<h2 id="_uploading_files">5. Uploading Files</h2>
<div class="sectionbody">
-<div class="paragraph"><p>A common task is uploading some sort of file, whether it&#8217;s a picture of a person or a CSV file containing data to process. The most important thing to remember with file uploads is that the form&#8217;s encoding <strong>MUST</strong> be set to multipart/form-data. If you forget to do this the file will not be uploaded. This can be done by passing <tt>:multi_part =&gt; true</tt> as an HTML option. This means that in the case of <tt>form_tag</tt> it must be passed in the second options hash and in the case of <tt>form_for</tt> inside the <tt>:html</tt> hash.</p></div>
+<div class="paragraph"><p>A common task is uploading some sort of file, whether it&#8217;s a picture of a person or a CSV file containing data to process. The most important thing to remember with file uploads is that the form&#8217;s encoding <strong>MUST</strong> be set to "multipart/form-data". If you forget to do this the file will not be uploaded. This can be done by passing <tt>:multi_part =&gt; true</tt> as an HTML option. This means that in the case of <tt>form_tag</tt> it must be passed in the second options hash and in the case of <tt>form_for</tt> inside the <tt>:html</tt> hash.</p></div>
<div class="paragraph"><p>The following two forms both upload a file.</p></div>
<div class="listingblock">
<div class="content">
@@ -724,7 +751,7 @@ The model object helpers for dates and times submit parameters with special name
</div></div>
<div class="paragraph"><p>Rails provides the usual pair of helpers: the barebones <tt>file_field_tag</tt> and the model oriented <tt>file_field</tt>. The only difference with other helpers is that you cannot set a default value for file inputs as this would have no meaning. As you would expect in the first case the uploaded file is in <tt>params[:picture]</tt> and in the second case in <tt>params[:person][:picture]</tt>.</p></div>
<h3 id="_what_gets_uploaded">5.1. What gets uploaded</h3>
-<div class="paragraph"><p>The object in the params hash is an instance of a subclass of IO. Depending on the size of the uploaded file it may in fact be a StringIO or an instance of File backed by a temporary file. In both cases the object will have an <tt>original_filename</tt> attribute containing the name the file had on the user&#8217;s computer and a <tt>content_type</tt> attribute containing the MIME type of the uploaded file. The following snippet saves the uploaded content in <tt>#{RAILS_ROOT}/public/uploads</tt> under the same name as the original file (assuming the form was the one in the previous example).</p></div>
+<div class="paragraph"><p>The object in the <tt>params</tt> hash is an instance of a subclass of IO. Depending on the size of the uploaded file it may in fact be a StringIO or an instance of File backed by a temporary file. In both cases the object will have an <tt>original_filename</tt> attribute containing the name the file had on the user&#8217;s computer and a <tt>content_type</tt> attribute containing the MIME type of the uploaded file. The following snippet saves the uploaded content in <tt>#{Rails.root}/public/uploads</tt> under the same name as the original file (assuming the form was the one in the previous example).</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -746,14 +773,14 @@ http://www.gnu.org/software/src-highlite -->
</tr></table>
</div>
<h3 id="_dealing_with_ajax">5.2. Dealing with Ajax</h3>
-<div class="paragraph"><p>Unlike other forms making an asynchronous file upload form is not as simple as replacing <tt>form_for</tt> with <tt>remote_form_for</tt>. With an AJAX form the serialization is done by javascript running inside the browser and since javascript cannot read files from your hard drive the file cannot be uploaded. The most common workaround is to use an invisible iframe that serves as the target for the form submission.</p></div>
+<div class="paragraph"><p>Unlike other forms making an asynchronous file upload form is not as simple as replacing <tt>form_for</tt> with <tt>remote_form_for</tt>. With an Ajax form the serialization is done by JavaScript running inside the browser and since JavaScript cannot read files from your hard drive the file cannot be uploaded. The most common workaround is to use an invisible iframe that serves as the target for the form submission.</p></div>
</div>
<h2 id="_customising_form_builders">6. Customising Form Builders</h2>
<div class="sectionbody">
-<div class="paragraph"><p>As mentioned previously the object yielded by <tt>form_for</tt> and <tt>fields_for</tt> is an instance of FormBuilder (or a subclass thereof). Form builders encapsulate the notion of displaying a form elements for a single object. While you can of course write helpers for your forms in the usual way you can also subclass FormBuilder and add the helpers there. For example</p></div>
+<div class="paragraph"><p>As mentioned previously the object yielded by <tt>form_for</tt> and <tt>fields_for</tt> is an instance of FormBuilder (or a subclass thereof). Form builders encapsulate the notion of displaying form elements for a single object. While you can of course write helpers for your forms in the usual way you can also subclass FormBuilder and add the helpers there. For example</p></div>
<div class="listingblock">
<div class="content">
-<pre><tt>&lt;% form_for @person do |f| %&gt;
+<pre><tt>&lt;% form_for @person do |f| %&gt;
&lt;%= text_field_with_label f, :first_name %&gt;
&lt;% end %&gt;</tt></pre>
</div></div>
@@ -771,7 +798,7 @@ 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> LabellingFormBuilder <span style="color: #990000">&lt;</span> FormBuilder
- <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> text_field attribute<span style="color: #990000">,</span> options<span style="color: #990000">=</span><span style="color: #FF0000">{}</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> text_field<span style="color: #990000">(</span>attribute<span style="color: #990000">,</span> options<span style="color: #990000">=</span><span style="color: #FF0000">{}</span><span style="color: #990000">)</span>
label<span style="color: #990000">(</span>attribute<span style="color: #990000">)</span> <span style="color: #990000">+</span> text_field<span style="color: #990000">(</span>attribute<span style="color: #990000">,</span> options<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>
@@ -781,13 +808,13 @@ http://www.gnu.org/software/src-highlite -->
<div class="content">
<pre><tt>&lt;%= render :partial =&gt; f %&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>If <tt>f</tt> is an instance of FormBuilder then this will render the <em>form</em> partial, setting the partial&#8217;s object to the form builder. If the form builder is of class LabellingFormBuilder then the <em>labelling_form</em> partial would be rendered instead.</p></div>
+<div class="paragraph"><p>If <tt>f</tt> is an instance of FormBuilder then this will render the <tt>form</tt> partial, setting the partial&#8217;s object to the form builder. If the form builder is of class LabellingFormBuilder then the <tt>labelling_form</tt> partial would be rendered instead.</p></div>
</div>
<h2 id="_understanding_parameter_naming_conventions">7. Understanding Parameter Naming Conventions</h2>
<div class="sectionbody">
-<div class="paragraph" id="parameter_names"><p>As you&#8217;ve seen in the previous sections, values from forms can appear either at the top level of the params hash or may appear nested in another hash. For example in a standard create
-action for a Person model, <tt>params[:model]</tt> would usually be a hash of all the attributes for the person to create. The params hash can also contain arrays, arrays of hashes and so on.</p></div>
-<div class="paragraph"><p>Fundamentally HTML forms don&#8217;t know about any sort of structured data, all they generate is name-value pairs. The arrays and hashes you see in your application are the result of some parameter naming conventions that Rails uses.</p></div>
+<div class="paragraph" id="parameter_names"><p>As you&#8217;ve seen in the previous sections, values from forms can be at the top level of the <tt>params</tt> hash or nested in another hash. For example in a standard <tt>create</tt>
+action for a Person model, <tt>params[:model]</tt> would usually be a hash of all the attributes for the person to create. The <tt>params</tt> hash can also contain arrays, arrays of hashes and so on.</p></div>
+<div class="paragraph"><p>Fundamentally HTML forms don&#8217;t know about any sort of structured data, all they generate is name-value pairs, where pairs are just plain strings. The arrays and hashes you see in your application are the result of some parameter naming conventions that Rails uses.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -797,38 +824,34 @@ action for a Person model, <tt>params[:model]</tt> would usually be a hash of al
<div class="paragraph"><p>You may find you can try out examples in this section faster by using the console to directly invoke Rails' parameter parser. For example</p></div>
<div class="listingblock">
<div class="content">
-<pre><tt>ActionController::RequestParser.parse_query_parameters "name=fred&amp;phone=0123456789"
-#=&gt; {"name"=&gt;"fred", "phone"=&gt;"0123456789"}</tt></pre>
+<pre><tt>ActionController::UrlEncodedPairParser.parse_query_parameters "name=fred&amp;phone=0123456789"
+# =&gt; {"name"=&gt;"fred", "phone"=&gt;"0123456789"}</tt></pre>
</div></div>
</td>
</tr></table>
</div>
<h3 id="_basic_structures">7.1. Basic structures</h3>
-<div class="paragraph"><p>The two basic structures are arrays and hashes. Hashes mirror the syntax used for accessing the value in the params. For example if a form contains</p></div>
+<div class="paragraph"><p>The two basic structures are arrays and hashes. Hashes mirror the syntax used for accessing the value in <tt>params</tt>. For example if a form contains</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;input id="person_name" name="person[name]" type="text" value="Henry"/&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>the params hash will contain</p></div>
+<div class="paragraph"><p>the <tt>params</tt> hash will contain</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: #FF0000">{</span><span style="color: #FF0000">'person'</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span><span style="color: #FF0000">'name'</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Henry'</span><span style="color: #FF0000">}}</span></tt></pre></div></div>
+<div class="content">
+<pre><tt>{'person' =&gt; {'name' =&gt; 'Henry'}}</tt></pre>
+</div></div>
<div class="paragraph"><p>and <tt>params["name"]</tt> will retrieve the submitted value in the controller.</p></div>
<div class="paragraph"><p>Hashes can be nested as many levels as required, for example</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;input id="person_address_city" name="person[address][city]" type="text" value="New York"/&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>will result in the params hash being</p></div>
+<div class="paragraph"><p>will result in the <tt>params</tt> hash being</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: #FF0000">{</span><span style="color: #FF0000">'person'</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span><span style="color: #FF0000">'address'</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span><span style="color: #FF0000">'city'</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'New York'</span><span style="color: #FF0000">}}}</span></tt></pre></div></div>
+<div class="content">
+<pre><tt>{'person' =&gt; {'address' =&gt; {'city' =&gt; 'New York'}}}</tt></pre>
+</div></div>
<div class="paragraph"><p>Normally Rails ignores duplicate parameter names. If the parameter name contains [] then they will be accumulated in an array. If you wanted people to be able to input multiple phone numbers, your could place this in the form:</p></div>
<div class="listingblock">
<div class="content">
@@ -845,23 +868,23 @@ http://www.gnu.org/software/src-highlite -->
&lt;input name="addresses[][line2]" type="text"/&gt;
&lt;input name="addresses[][city]" type="text"/&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>This would result in <tt>params[:addresses]</tt> being an array of hashes with keys <tt>line1</tt>, <tt>line2</tt> and <tt>city</tt>. Rails decides to start accumulating values in a new hash whenever it encounters a input name that already exists in the current hash.</p></div>
-<div class="paragraph"><p>The one restriction is that although hashes can be nested arbitrarily deep then can be only one level of "arrayness". Frequently arrays can be usually replaced by hashes, for example instead of having an array of model objects one can have a hash of model objects keyed by their id.</p></div>
+<div class="paragraph"><p>This would result in <tt>params[:addresses]</tt> being an array of hashes with keys <tt>line1</tt>, <tt>line2</tt> and <tt>city</tt>. Rails decides to start accumulating values in a new hash whenever it encounters an input name that already exists in the current hash.</p></div>
+<div class="paragraph"><p>There&#8217;s a restriction, however, while hashes can be nested arbitrarily, only one level of "arrayness" is allowed. Arrays can be usually replaced by hashes, for example instead of having an array of model objects one can have a hash of model objects keyed by their id, an array index or some other parameter.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/warning.png" alt="Warning" />
</td>
-<td class="content">Array parameters do not play well with the <tt>check_box</tt> helper. According to the HTML specification unchecked checkboxes submit no value. However it is often convenient for a checkbox to always submit a value. The <tt>check_box</tt> helper fakes this by creating a second hidden input with the same name. If the checkbox is unchecked only the hidden input is submitted. If the checkbox is checked then both are submitted but the value submitted by the checkbox takes precedence. When working with array parameters this duplicate submission will confuse Rails since duplicate input names are how it decides when to start a new hash. It is preferable to either use <tt>check_box_tag</tt> or to use hashes instead of arrays.</td>
+<td class="content">Array parameters do not play well with the <tt>check_box</tt> helper. According to the HTML specification unchecked checkboxes submit no value. However it is often convenient for a checkbox to always submit a value. The <tt>check_box</tt> helper fakes this by creating a second hidden input with the same name. If the checkbox is unchecked only the hidden input is submitted and if it is checked then both are submitted but the value submitted by the checkbox takes precedence. When working with array parameters this duplicate submission will confuse Rails since duplicate input names are how it decides when to start a new array element. It is preferable to either use <tt>check_box_tag</tt> or to use hashes instead of arrays.</td>
</tr></table>
</div>
<h3 id="_using_form_helpers">7.3. Using form helpers</h3>
-<div class="paragraph"><p>The previous sections did not use the Rails form helpers at all. While you can craft the input names yourself and pass them directly to helpers such as <tt>text_field_tag</tt> Rails also provides higher level support. The two tools at your disposal here are the name parameter to <tt>form_for</tt>/<tt>fields_for</tt> and the <tt>:index</tt> option.</p></div>
-<div class="paragraph"><p>You might want to render a form with a set of edit fields for each of a person&#8217;s addresses. Something a little like this will do the trick</p></div>
+<div class="paragraph"><p>The previous sections did not use the Rails form helpers at all. While you can craft the input names yourself and pass them directly to helpers such as <tt>text_field_tag</tt> Rails also provides higher level support. The two tools at your disposal here are the name parameter to <tt>form_for</tt> and <tt>fields_for</tt> and the <tt>:index</tt> option that helpers take.</p></div>
+<div class="paragraph"><p>You might want to render a form with a set of edit fields for each of a person&#8217;s addresses. For example:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;% form_for @person do |person_form| %&gt;
- &lt;%= person_form.text_field :name%&gt;
+ &lt;%= person_form.text_field :name %&gt;
&lt;% for address in @person.addresses %&gt;
&lt;% person_form.fields_for address, :index =&gt; address do |address_form|%&gt;
&lt;%= address_form.text_field :city %&gt;
@@ -869,7 +892,7 @@ http://www.gnu.org/software/src-highlite -->
&lt;% end %&gt;
&lt;% end %&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>Assuming our person had two addresses, with ids 23 and 45 this would create output similar to this:</p></div>
+<div class="paragraph"><p>Assuming the person had two addresses, with ids 23 and 45 this would create output similar to this:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>&lt;form action="/people/1" class="edit_person" id="edit_person_1" method="post"&gt;
@@ -878,14 +901,12 @@ http://www.gnu.org/software/src-highlite -->
&lt;input id="person_address_45_city" name="person[address][45][city]" size="30" type="text" /&gt;
&lt;/form&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>This will result in a params hash that looks like</p></div>
+<div class="paragraph"><p>This will result in a <tt>params</tt> hash that 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="color: #FF0000">{</span><span style="color: #FF0000">'person'</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span><span style="color: #FF0000">'name'</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Bob'</span><span style="color: #990000">,</span> <span style="color: #FF0000">'address'</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span> <span style="color: #FF0000">'23'</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span><span style="color: #FF0000">'city'</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Paris'</span><span style="color: #FF0000">}</span><span style="color: #990000">,</span> <span style="color: #FF0000">'45'</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">{</span><span style="color: #FF0000">'city'</span> <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'London'</span><span style="color: #FF0000">}</span> <span style="color: #FF0000">}}}</span></tt></pre></div></div>
-<div class="paragraph"><p>Rails knows that all these inputs should be part of the person hash because you called <tt>fields_for</tt> on the first form builder. By specifying an <tt>:index</tt> option you&#8217;re telling rails that instead of naming the inputs <tt>person[address][city]</tt> it should insert that index surrounded by [] between the address and the city. If you pass an Active Record object as we did then Rails will call <tt>to_param</tt> on it, which by default returns the database id. This is often useful it is then easy to locate which Address record should be modified but you could pass numbers with some other significance, strings or even nil (which will result in an array parameter being created).</p></div>
+<div class="content">
+<pre><tt>{'person' =&gt; {'name' =&gt; 'Bob', 'address' =&gt; {'23' =&gt; {'city' =&gt; 'Paris'}, '45' =&gt; {'city' =&gt; 'London'}}}}</tt></pre>
+</div></div>
+<div class="paragraph"><p>Rails knows that all these inputs should be part of the person hash because you called <tt>fields_for</tt> on the first form builder. By specifying an <tt>:index</tt> option you&#8217;re telling rails that instead of naming the inputs <tt>person[address][city]</tt> it should insert that index surrounded by [] between the address and the city. If you pass an Active Record object as we did then Rails will call <tt>to_param</tt> on it, which by default returns the database id. This is often useful as it is then easy to locate which Address record should be modified. You can pass numbers with some other significance, strings or even <tt>nil</tt> (which will result in an array parameter being created).</p></div>
<div class="paragraph"><p>To create more intricate nestings, you can specify the first part of the input name (<tt>person[address]</tt> in the previous example) explicitly, for example</p></div>
<div class="listingblock">
<div class="content">
@@ -898,7 +919,7 @@ http://www.gnu.org/software/src-highlite -->
<div class="content">
<pre><tt>&lt;input id="person_address_primary_1_city" name="person[address][primary][1][city]" size="30" type="text" value="bologna" /&gt;</tt></pre>
</div></div>
-<div class="paragraph"><p>As a general rule the final input name is the concatenation of the name given to <tt>fields_for</tt>/<tt>form_for</tt>, the index value and the name of the attribute. You can also pass an <tt>:index</tt> option directly to helpers such as <tt>text_field</tt>, but usually it is less repetitive to specify this at the form builder level rather than on individual input controls.</p></div>
+<div class="paragraph"><p>As a general rule the final input name is the concatenation of the name given to <tt>fields_for</tt>/<tt>form_for</tt>, the index value and the name of the attribute. You can also pass an <tt>:index</tt> option directly to helpers such as <tt>text_field</tt>, but it is usually less repetitive to specify this at the form builder level rather than on individual input controls.</p></div>
<div class="paragraph"><p>As a shortcut you can append [] to the name and omit the <tt>:index</tt> option. This is the same as specifing <tt>:index =&gt; address</tt> so</p></div>
<div class="listingblock">
<div class="content">
@@ -910,7 +931,7 @@ http://www.gnu.org/software/src-highlite -->
</div>
<h2 id="_building_complex_forms">8. Building Complex forms</h2>
<div class="sectionbody">
-<div class="paragraph"><p>Many apps grow beyond simple forms editing a single object. For example when creating a Person instance you might want to allow the user to (on the same form) create multiple address records (home, work etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary. While this guide has shown you all the pieces necessary to handle this, Rails does not yet have a standard end-to-end way of accomplishing this, but many have come up with viable approaches. These include:</p></div>
+<div class="paragraph"><p>Many apps grow beyond simple forms editing a single object. For example when creating a Person you might want to allow the user to (on the same form) create multiple address records (home, work, etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary. While this guide has shown you all the pieces necessary to handle this, Rails does not yet have a standard end-to-end way of accomplishing this, but many have come up with viable approaches. These include:</p></div>
<div class="ulist"><ul>
<li>
<p>
diff --git a/railties/doc/guides/html/i18n.html b/railties/doc/guides/html/i18n.html
index 386b801d64..b0d52c0ff5 100644
--- a/railties/doc/guides/html/i18n.html
+++ b/railties/doc/guides/html/i18n.html
@@ -54,16 +54,20 @@
<li><a href="#_setting_locale_from_the_url_params">Setting locale from the URL params</a></li>
+ <li><a href="#_setting_locale_from_the_client_supplied_information">Setting locale from the client supplied information</a></li>
+
</ul>
</li>
<li>
- <a href="#_internationalize_your_application">Internationalize your application</a>
+ <a href="#_internationalizing_your_application">Internationalizing your application</a>
<ul>
<li><a href="#_adding_translations">Adding Translations</a></li>
<li><a href="#_adding_date_time_formats">Adding Date/Time formats</a></li>
+ <li><a href="#_organization_of_locale_files">Organization of locale files</a></li>
+
</ul>
</li>
<li>
@@ -125,13 +129,51 @@
<h1>The Rails Internationalization (I18n) API</h1>
<div id="preamble">
<div class="sectionbody">
-<div class="paragraph"><p>The Ruby I18n (shorthand for <em>internationalization</em>) gem which is shipped with Ruby on Rails (starting from Rails 2.2) provides an easy-to-use and extensible framework for translating your application to a single custom language other than English or providing multi-language support in your application.</p></div>
+<div class="paragraph"><p>The Ruby I18n (shorthand for <em>internationalization</em>) gem which is shipped with Ruby on Rails (starting from Rails 2.2) provides an easy-to-use and extensible framework for <strong>translating your application to a single custom language</strong> other than English or for <strong>providing multi-language support</strong> in your application.</p></div>
+<div class="paragraph"><p>The process of "internationalization" usually means to abstract all strings and other locale specific bits (such as date or currency formats) out of your application. The process of "localization" means to provide translations and localized formats for these bits. <a href="#1">[1]</a></p></div>
+<div class="paragraph"><p>So, in the process of <em>internationalizing</em> your Rails application you have to:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Ensure you have support for i18n
+</p>
+</li>
+<li>
+<p>
+Tell Rails where to find locale dictionaries
+</p>
+</li>
+<li>
+<p>
+Tell Rails how to set, preserve and switch locale
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>In the process of <em>localizing</em> your application you&#8217;ll probably want to do following three things:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+Replace or supplement Rail&#8217;s default locale&#8201;&#8212;&#8201;eg. date and time formats, month names, ActiveRecord model names, etc
+</p>
+</li>
+<li>
+<p>
+Abstract texts in your application into keyed dictionaries&#8201;&#8212;&#8201;eg. flash messages, static texts in your views, etc
+</p>
+</li>
+<li>
+<p>
+Store the resulting dictionaries somewhere
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>This guide will walk you through the I18n API and contains a tutorial how to internationalize a Rails application from the start.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
-<td class="content">The Ruby I18n framework provides you with all neccessary means for internationalization/localization of your Rails application. You may, however, use any of various plugins and extensions available. See Rails <a href="http://rails-i18n.org/wiki">I18n Wiki</a> for more information.</td>
+<td class="content">The Ruby I18n framework provides you with all neccessary means for internationalization/localization of your Rails application. You may, however, use any of various plugins and extensions available, which add additional functionality or features. See Rails <a href="http://rails-i18n.org/wiki">I18n Wiki</a> for more information.</td>
</tr></table>
</div>
</div>
@@ -221,6 +263,14 @@ http://www.gnu.org/software/src-highlite -->
hello<span style="color: #990000">:</span> <span style="color: #FF0000">"Hello world"</span></tt></pre></div></div>
<div class="paragraph"><p>This means, that in the <tt>:en</tt> locale, the key <em>hello</em> will map to <em>Hello world</em> string. Every string inside Rails is internationalized in this way, see for instance Active Record validation messages in the <a href="http://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml"><tt>activerecord/lib/active_record/locale/en.yml</tt></a> file or time and date formats in the <a href="http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml"><tt>activesupport/lib/active_support/locale/en.yml</tt></a> file. You can use YAML or standard Ruby Hashes to store translations in the default (Simple) backend.</p></div>
<div class="paragraph"><p>The I18n library will use <strong>English</strong> as a <strong>default locale</strong>, ie. if you don&#8217;t set a different locale, <tt>:en</tt> will be used for looking up translations.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="./images/icons/note.png" alt="Note" />
+</td>
+<td class="content">The i18n library takes <strong>pragmatic approach</strong> to locale keys (after <a href="http://groups.google.com/group/rails-i18n/browse_thread/thread/14dede2c7dbe9470/80eec34395f64f3c?hl=en">some discussion</a>), including only the <em>locale</em> ("language") part, like <tt>:en</tt>, <tt>:pl</tt>, not the <em>region</em> part, like <tt>:en-US</tt> or <tt>:en-UK</tt>, which are traditionally used for separating "languages" and "regional setting" or "dialects". (For instance, in the <tt>:en-US</tt> locale you would have $ as a currency symbol, while in <tt>:en-UK</tt>, you would have €. Also, insults would be different in American and British English :) Reason for this pragmatic approach is that most of the time, you usually care about making your application available in different "languages", and working with locales is much simpler this way. However, nothing stops you from separating regional and other settings in the traditional way. In this case, you could eg. inherit from the default <tt>en</tt> locale and then provide UK specific settings in a <tt>:en-UK</tt> dictionary.</td>
+</tr></table>
+</div>
<div class="paragraph"><p>The <strong>translations load path</strong> (<tt>I18n.load_path</tt>) is just a Ruby Array of paths to your translation files that will be loaded automatically and available in your application. You can pick whatever directory and translation file naming scheme makes sense for you.</p></div>
<div class="admonitionblock">
<table><tr>
@@ -264,7 +314,7 @@ I18n<span style="color: #990000">.</span>default_locale <span style="color: #990
<td class="icon">
<img src="./images/icons/warning.png" alt="Warning" />
</td>
-<td class="content">You may be tempted to store choosed locale in a <em>session</em> or a <em>cookie</em>. <strong>Do not do so</strong>. The locale should be transparent and a part of the URL. This way you don&#8217;t break people&#8217;s basic assumptions about the web itself: if you send a URL of some page to a friend, she should see the same page, same content. A fancy word for this would be that you&#8217;re being <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"><em>RESTful</em></a>. There may be some exceptions to this rule, which are discussed below.</td>
+<td class="content">You may be tempted to store choosed locale in a <em>session</em> or a <em>cookie</em>. <strong>Do not do so</strong>. The locale should be transparent and a part of the URL. This way you don&#8217;t break people&#8217;s basic assumptions about the web itself: if you send a URL of some page to a friend, she should see the same page, same content. A fancy word for this would be that you&#8217;re being <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"><em>RESTful</em></a>. Read more about RESTful approach in <a href="http://www.infoq.com/articles/rest-introduction">Stefan Tilkov&#8217;s articles</a>. There may be some exceptions to this rule, which are discussed below.</td>
</tr></table>
</div>
<div class="paragraph"><p>The <em>setting part</em> is easy. You can set locale in a <tt>before_filter</tt> in the ApplicationController like this:</p></div>
@@ -278,7 +328,7 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-style: italic"><span style="color: #9A1900"># if params[:locale] is nil then I18n.default_locale will be used</span></span>
I18n<span style="color: #990000">.</span>locale <span style="color: #990000">=</span> params<span style="color: #990000">[:</span>locale<span style="color: #990000">]</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
-<div class="paragraph"><p>This requires you to pass the locale as a URL query parameter as in <tt>http://example.com/books?locale=pt</tt>. (This is eg. Google&#8217;s approach). So <tt>http://localhost:3000?locale=pt</tt> will load the Portugese localization, whereas <tt>http://localhost:3000?locale=de</tt> would load the German localization, and so on.</p></div>
+<div class="paragraph"><p>This requires you to pass the locale as a URL query parameter as in <tt>http://example.com/books?locale=pt</tt>. (This is eg. Google&#8217;s approach). So <tt>http://localhost:3000?locale=pt</tt> will load the Portugese localization, whereas <tt>http://localhost:3000?locale=de</tt> would load the German localization, and so on. You may skip the next section and head over to the <strong>Internationalize your application</strong> section, if you want to try things out by manually placing locale in the URL and reloading the page.</p></div>
<div class="paragraph"><p>Of course, you probably don&#8217;t want to manually include locale in every URL all over your application, or want the URLs look differently, eg. the usual <tt>http://example.com/pt/books</tt> versus <tt>http://example.com/en/books</tt>. Let&#8217;s discuss the different options you have.</p></div>
<div class="admonitionblock">
<table><tr>
@@ -288,7 +338,7 @@ http://www.gnu.org/software/src-highlite -->
<td class="content">Following examples rely on having locales loaded into your application available as an array of strings like <tt>["en", "es", "gr"]</tt>. This is not inclued in current version of Rails 2.2&#8201;&#8212;&#8201;forthcoming Rails version 2.3 will contain easy accesor <tt>available_locales</tt>. (See <a href="http://github.com/svenfuchs/i18n/commit/411f8fe7">this commit</a> and background at <a href="http://rails-i18n.org/wiki/pages/i18n-available_locales">Rails I18n Wiki</a>.)</td>
</tr></table>
</div>
-<div class="paragraph"><p>We have to include support for getting available locales manually in an initializer like this:</p></div>
+<div class="paragraph"><p>So, for having available locales easily available in Rails 2.2, we have to include this support manually in an initializer, like this:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -324,7 +374,7 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> available_locales<span style="color: #990000">;</span> AVAILABLE_LOCALES<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>
<h3 id="_setting_locale_from_the_domain_name">2.4. Setting locale from the domain name</h3>
-<div class="paragraph"><p>One option you have is to set the locale from the domain name, where your application runs. For example, we want <tt>www.example.com</tt> to load English (or default) locale, and <tt>www.example.es</tt> to load Spanish locale. Thus the <em>top-level domain name</em> is used for locale setting. This has several advantages:</p></div>
+<div class="paragraph"><p>One option you have is to set the locale from the domain name where your application runs. For example, we want <tt>www.example.com</tt> to load English (or default) locale, and <tt>www.example.es</tt> to load Spanish locale. Thus the <em>top-level domain name</em> is used for locale setting. This has several advantages:</p></div>
<div class="ulist"><ul>
<li>
<p>
@@ -381,33 +431,90 @@ http://www.gnu.org/software/src-highlite -->
parsed_locale <span style="color: #990000">=</span> request<span style="color: #990000">.</span>subdomains<span style="color: #990000">.</span>first
<span style="color: #990000">(</span>available_locales<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">include</span></span><span style="color: #990000">?</span> parsed_locale<span style="color: #990000">)</span> <span style="color: #990000">?</span> parsed_locale <span style="color: #990000">:</span> <span style="font-weight: bold"><span style="color: #0000FF">nil</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
+<div class="paragraph"><p>If your application includes a locale switching menu, you would then have something like this in 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>link_to<span style="color: #990000">(</span><span style="color: #FF0000">"Deutsch"</span><span style="color: #990000">,</span> <span style="color: #FF0000">"#{APP_CONFIG[:deutsch_website_url]}#{request.env['REQUEST_URI']}"</span><span style="color: #990000">)</span></tt></pre></div></div>
+<div class="paragraph"><p>assuming you would set <tt>APP_CONFIG[:deutsch_website_url]</tt> to some value like <tt>http://www.application.de</tt>.</p></div>
+<div class="paragraph"><p>This solution has aforementioned advantages, however, you may not be able or may not want to provide different localizations ("language versions") on different domains. The most obvious solution would be to include locale code in the URL params (or request path).</p></div>
<h3 id="_setting_locale_from_the_url_params">2.5. Setting locale from the URL params</h3>
-<div class="ulist"><ul>
-<li>
-<p>
-TODO : Based on <strong><tt>default_url options</tt></strong>, <a href="http://github.com/karmi/test_default_url_options/blob/master/app/controllers/application.rb#L22-26">http://github.com/karmi/test_default_url_options/blob/master/app/controllers/application.rb#L22-26</a>
-</p>
-</li>
-<li>
-<p>
-TODO : Discussion of plugins (translate_routes and routing_filter)
-</p>
-</li>
-</ul></div>
+<div class="paragraph"><p>Most usual way of setting (and passing) the locale would be to include it in URL params, as we did in the <tt>I18n.locale = params[:locale]</tt> <em>before_filter</em> in the first example. We would like to have URLs like <tt>www.example.com/books?locale=ja</tt> or <tt>www.example.com/ja/books</tt> in this case.</p></div>
+<div class="paragraph"><p>This approach has almost the same set of advantages as setting the locale from domain name: namely that it&#8217;s RESTful and in accord with rest of the World Wide Web. It does require a little bit more work to implement, though.</p></div>
+<div class="paragraph"><p>Getting the locale from <tt>params</tt> and setting it accordingly is not hard; including it in every URL and thus <strong>passing it through the requests</strong> is. To include an explicit option in every URL (eg. <tt>link_to( books_url(:locale =&gt; I18n.locale) )</tt>) would be tedious and probably impossible, of course.</p></div>
+<div class="paragraph"><p>Rails contains infrastructure for "centralizing dynamic decisions about the URLs" in its <a href="http://api.rubyonrails.org/classes/ActionController/Base.html#M000515"><tt><strong>ApplicationController#default_url_options</strong></tt></a>, which is useful precisely in this scenario: it enables us to set "defaults" for <a href="http://api.rubyonrails.org/classes/ActionController/Base.html#M000503"><tt>url_for</tt></a> and helper methods dependent on it (by implementing/overriding this method).</p></div>
+<div class="paragraph"><p>We can include something like this in our ApplicationController then:</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"># app/controllers/application_controller.rb</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> default_url_options<span style="color: #990000">(</span>options<span style="color: #990000">=</span><span style="color: #FF0000">{}</span><span style="color: #990000">)</span>
+ logger<span style="color: #990000">.</span>debug <span style="color: #FF0000">"default_url_options is passed options: #{options.inspect}\n"</span>
+ <span style="color: #FF0000">{</span> <span style="color: #990000">:</span>locale <span style="color: #990000">=&gt;</span> I18n<span style="color: #990000">.</span>locale <span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
+<div class="paragraph"><p>Every helper method dependent on <tt>url_for</tt> (eg. helpers for named routes like <tt>root_path</tt> or <tt>root_url</tt>, resource routes like <tt>books_path</tt> or <tt>books_url</tt>, etc.) will now <strong>automatically include the locale in the query string</strong>, like this: <tt>http://localhost:3001/?locale=ja</tt>.</p></div>
+<div class="paragraph"><p>You may be satisfied with this. It does impact the readability of URLs, though, when the locale "hangs" at the end of every URL in your application. Moreover, from the architectural standpoint, locale is usually hierarchically above the other parts of application domain: and URLs should reflect this.</p></div>
+<div class="paragraph"><p>You probably want URLs look like this: <tt>www.example.com/en/books</tt> (which loads English locale) and <tt>www.example.com/nl/books</tt> (which loads Netherlands locale). This is achievable with the "over-riding <tt>default_url_options</tt>" strategy from above: you just have to set up your routes with <a href="http://api.rubyonrails.org/classes/ActionController/Resources.html#M000354"><tt>path_prefix</tt></a> option in this 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><span style="font-style: italic"><span style="color: #9A1900"># config/routes.rb</span></span>
+map<span style="color: #990000">.</span>resources <span style="color: #990000">:</span>books<span style="color: #990000">,</span> <span style="color: #990000">:</span>path_prefix <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'/:locale'</span></tt></pre></div></div>
+<div class="paragraph"><p>Now, when you call <tt>books_path</tt> method you should get <tt>"/en/books"</tt> (for the default locale). An URL like <tt>http://localhost:3001/nl/books</tt> should load the Netherlands locale, then, and following calls to <tt>books_path</tt> should return <tt>"/nl/books"</tt> (because the locale changed).</p></div>
+<div class="paragraph"><p>Of course, you need to take special care of root URL (usually "homepage" or "dashboard") of your application. An URL like <tt>http://localhost:3001/nl</tt> will not work automatically, because the <tt>map.root :controller =&gt; "dashboard"</tt> declaration in your <tt>routes.rb</tt> doesn&#8217;t take locale into account. (And rightly so. There&#8217;s only one "root" URL.)</p></div>
+<div class="paragraph"><p>You would probably need to map URLs like these:</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"># config/routes.rb</span></span>
+map<span style="color: #990000">.</span>dashboard <span style="color: #FF0000">'/:locale'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>controller <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"dashboard"</span></tt></pre></div></div>
+<div class="paragraph"><p>Do take special care about the <strong>order of your routes</strong>, so this route declaration does not "eat" other ones. (You may want to add it directly before the <tt>map.root</tt> declaration.)</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
-<img src="./images/icons/tip.png" alt="Tip" />
+<img src="./images/icons/important.png" alt="Important" />
</td>
-<td class="content">For setting locale from URL see <a href="http://rails-i18n.org/wiki/pages/how-to-encode-the-current-locale-in-the-url">How to encode the current locale in the URL</a> in the Rails i18n Wiki.</td>
+<td class="content">This solution has currently one rather big <strong>downside</strong>. Due to the <em>default_url_options</em> implementation, you have to pass the <tt>:id</tt> option explicitely, like this: <tt>link_to <em>Show</em>, book_url(:id =&gt; book)</tt> and not depend on Rails' magic in code like <tt>link_to <em>Show</em>, book</tt>. If this should be a problem, have a look on two plugins which simplify working with routes in this way: Sven Fuchs&#8217;s <a href="http://github.com/svenfuchs/routing-filter/tree/master"><em>routing_filter</em></a> and Raul Murciano&#8217;s <a href="http://github.com/raul/translate_routes/tree/master"><em>translate_routes</em></a>. See also the page <a href="http://rails-i18n.org/wiki/pages/how-to-encode-the-current-locale-in-the-url">How to encode the current locale in the URL</a> in the Rails i18n Wiki.</td>
</tr></table>
</div>
-<div class="paragraph"><p>Now you&#8217;ve initialized I18n support for your application and told it which locale should be used. With that in place you&#8217;re now ready for the really interesting stuff.</p></div>
+<h3 id="_setting_locale_from_the_client_supplied_information">2.6. Setting locale from the client supplied information</h3>
+<div class="paragraph"><p>In specific cases, it would make sense to set locale from client supplied information, ie. not from URL. This information may come for example from users' preffered language (set in their browser), can be based on users' geographical location inferred from their IP, or users can provide it simply by choosing locale in your application interface and saving it to their profile. This approach is more suitable for web-based applications or services, not for websites&#8201;&#8212;&#8201;see the box about <em>sessions</em>, <em>cookies</em> and RESTful architecture above.</p></div>
+<h4 id="_using_accept_language">2.6.1. Using Accept-Language</h4>
+<div class="paragraph"><p>One source of client supplied information would be an <tt>Accept-Language</tt> HTTP header. People may <a href="http://www.w3.org/International/questions/qa-lang-priorities">set this in their browser</a> or other clients (such as <em>curl</em>).</p></div>
+<div class="paragraph"><p>A trivial implementation of using <tt>Accept-Language</tt> header 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><span style="font-weight: bold"><span style="color: #0000FF">def</span></span> set_locale
+ logger<span style="color: #990000">.</span>debug <span style="color: #FF0000">"* Accept-Language: #{request.env['HTTP_ACCEPT_LANGUAGE']}"</span>
+ I18n<span style="color: #990000">.</span>locale <span style="color: #990000">=</span> extract_locale_from_accept_language_header
+ logger<span style="color: #990000">.</span>debug <span style="color: #FF0000">"* Locale set to '#{I18n.locale}'"</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+private
+<span style="font-weight: bold"><span style="color: #0000FF">def</span></span> extract_locale_from_accept_language_header
+ request<span style="color: #990000">.</span>env<span style="color: #990000">[</span><span style="color: #FF0000">'HTTP_ACCEPT_LANGUAGE'</span><span style="color: #990000">].</span>scan<span style="color: #990000">(</span><span style="color: #FF6600">/^[a-z]{2}/</span><span style="color: #990000">).</span>first
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
+<div class="paragraph"><p>Of course, in production environment you would need much robust code, and could use a plugin such as Iaian Hecker&#8217;s <a href="http://github.com/iain/http_accept_language">http_accept_language</a>.</p></div>
+<h4 id="_using_geoip_or_similar_database">2.6.2. Using GeoIP (or similar) database</h4>
+<div class="paragraph"><p>Another way of choosing the locale from client&#8217;s information would be to use a database for mapping client IP to region, such as <a href="http://www.maxmind.com/app/geolitecountry">GeoIP Lite Country</a>. The mechanics of the code would be very similar to the code above&#8201;&#8212;&#8201;you would need to query database for user&#8217;s IP, and lookup your preffered locale for the country/region/city returned.</p></div>
+<h4 id="_user_profile">2.6.3. User profile</h4>
+<div class="paragraph"><p>You can also provide users of your application with means to set (and possibly over-ride) locale in your application interface, as well. Again, mechanics for this approach would be very similar to the code above&#8201;&#8212;&#8201;you&#8217;d probably let users choose a locale from a dropdown list and save it to their profile in database. Then you&#8217;d set the locale to this value.</p></div>
</div>
-<h2 id="_internationalize_your_application">3. Internationalize your application</h2>
+<h2 id="_internationalizing_your_application">3. Internationalizing your application</h2>
<div class="sectionbody">
-<div class="paragraph"><p>The process of "internationalization" usually means to abstract all strings and other locale specific bits out of your application. The process of "localization" means to then provide translations and localized formats for these bits. <a href="#1">[1]</a></p></div>
-<div class="paragraph"><p>So, let&#8217;s internationalize something. You most probably have something like this in one of your applications:</p></div>
+<div class="paragraph"><p>OK! Now you&#8217;ve initialized I18n support for your Ruby on Rails application and told it which locale should be used and how to preserve it between requests. With that in place, you&#8217;re now ready for the really interesting stuff.</p></div>
+<div class="paragraph"><p>Let&#8217;s <em>internationalize</em> our application, ie. abstract every locale-specific parts, and that <em>localize</em> it, ie. provide neccessary translations for these abstracts.</p></div>
+<div class="paragraph"><p>You most probably have something like this in one of your applications:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -432,7 +539,7 @@ ActionController<span style="color: #990000">::</span>Routing<span style="color:
<img src="images/i18n/demo_untranslated.png" alt="rails i18n demo untranslated" title="rails i18n demo untranslated" />
</span></p></div>
<h3 id="_adding_translations">3.1. Adding Translations</h3>
-<div class="paragraph"><p>Obviously there are two strings that are localized to English. In order to internationalize this code replace these strings with calls to Rails' #t helper with a key that makes sense for the translation:</p></div>
+<div class="paragraph"><p>Obviously there are <strong>two strings that are localized to English</strong>. In order to internationalize this code, <strong>replace these strings</strong> with calls to Rails' <tt>#t</tt> helper with a key that makes sense for the translation:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -448,7 +555,7 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-style: italic"><span style="color: #9A1900"># app/views/home/index.html.erb</span></span>
<span style="color: #FF0000">&lt;h1&gt;&lt;%=t :hello_world %&gt;&lt;/h1&gt;</span>
<span style="color: #FF0000">&lt;p&gt;&lt;%= flash[:notice] %&gt;&lt;/p&gt;</span></tt></pre></div></div>
-<div class="paragraph"><p>When you now render this view it will show an error message that tells you that the translations for the keys :hello_world and :hello_flash are missing.</p></div>
+<div class="paragraph"><p>When you now render this view, it will show an error message which tells you that the translations for the keys <tt>:hello_world</tt> and <tt>:hello_flash</tt> are missing.</p></div>
<div class="paragraph"><p><span class="image">
<img src="images/i18n/demo_translation_missing.png" alt="rails i18n demo translation missing" title="rails i18n demo translation missing" />
</span></p></div>
@@ -457,10 +564,10 @@ http://www.gnu.org/software/src-highlite -->
<td class="icon">
<img src="./images/icons/note.png" alt="Note" />
</td>
-<td class="content">Rails adds a <tt>t</tt> (<tt>translate</tt>) helper method to your views so that you do not need to spell out <tt>I18n.t</tt> all the time. Additionally this helper will catch missing translations and wrap the resulting error message into a &lt;span class="translation_missing"&gt;.</td>
+<td class="content">Rails adds a <tt>t</tt> (<tt>translate</tt>) helper method to your views so that you do not need to spell out <tt>I18n.t</tt> all the time. Additionally this helper will catch missing translations and wrap the resulting error message into a <tt>&lt;span class="translation_missing"&gt;</tt>.</td>
</tr></table>
</div>
-<div class="paragraph"><p>So let&#8217;s add the missing translations (i.e. do the "localization" part):</p></div>
+<div class="paragraph"><p>So let&#8217;s add the missing translations into the dictionary files (i.e. do the "localization" part):</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -475,17 +582,24 @@ en<span style="color: #990000">:</span>
pirate<span style="color: #990000">:</span>
hello_world<span style="color: #990000">:</span> Ahoy World
hello_flash<span style="color: #990000">:</span> Ahoy Flash</tt></pre></div></div>
-<div class="paragraph"><p>There you go. Because you haven&#8217;t changed the default_locale I18n will use English. Your application now shows:</p></div>
+<div class="paragraph"><p>There you go. Because you haven&#8217;t changed the default_locale, I18n will use English. Your application now shows:</p></div>
<div class="paragraph"><p><span class="image">
<img src="images/i18n/demo_translated_en.png" alt="rails i18n demo translated to english" title="rails i18n demo translated to english" />
</span></p></div>
-<div class="paragraph"><p>And when you change the URL to pass the pirate locale you get:</p></div>
+<div class="paragraph"><p>And when you change the URL to pass the pirate locale (<tt>http://localhost:3000?locale=pirate</tt>), you&#8217;ll get:</p></div>
<div class="paragraph"><p><span class="image">
<img src="images/i18n/demo_translated_pirate.png" alt="rails i18n demo translated to pirate" title="rails i18n demo translated to pirate" />
</span></p></div>
-<div class="paragraph"><p>NOTE You need to restart the server when you add new locale files.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="./images/icons/note.png" alt="Note" />
+</td>
+<td class="content">You need to restart the server when you add new locale files.</td>
+</tr></table>
+</div>
<h3 id="_adding_date_time_formats">3.2. Adding Date/Time formats</h3>
-<div class="paragraph"><p>Ok, let&#8217;s add a timestamp to the view so we can demo the date/time localization feature as well. To localize the time format you pass the Time object to I18n.l or (preferably) use Rails' #l helper. You can pick a format by passing the :format option, by default the :default format is used.</p></div>
+<div class="paragraph"><p>OK! Now let&#8217;s add a timestamp to the view, so we can demo the <strong>date/time localization</strong> feature as well. To localize the time format you pass the Time object to <tt>I18n.l</tt> or (preferably) use Rails' <tt>#l</tt> helper. You can pick a format by passing the <tt>:format</tt> option&#8201;&#8212;&#8201;by default the <tt>:default</tt> format is used.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -510,30 +624,67 @@ pirate<span style="color: #990000">:</span>
<div class="paragraph"><p><span class="image">
<img src="images/i18n/demo_localized_pirate.png" alt="rails i18n demo localized time to pirate" title="rails i18n demo localized time to pirate" />
</span></p></div>
-<div class="paragraph"><p>NOTE Right now you might need to add some more date/time formats in order to make the I18n backend work as expected. See the <a href="http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale">rails-i18n repository</a> for starting points.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="./images/icons/tip.png" alt="Tip" />
+</td>
+<td class="content">Right now you might need to add some more date/time formats in order to make the I18n backend work as expected. Of course, there&#8217;s a great chance that somebody already did all the work by <strong>translating Rails&#8217;s defaults for your locale</strong>. See the <a href="http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale">rails-i18n repository at Github</a> for an archive of various locale files. When you put such file(s) in <tt>config/locale/</tt> directory, they will automatically ready for use.</td>
+</tr></table>
+</div>
+<h3 id="_organization_of_locale_files">3.3. Organization of locale files</h3>
+<div class="paragraph"><p>When you are using the default SimpleStore, shipped with the i18n library, you store dictionaries in plain-text files on the disc. Putting translations for all parts of your application in one file per locale could be hard to manage. You can store these files in a hierarchy which makes sense to you.</p></div>
+<div class="paragraph"><p>For example, your <tt>config/locale</tt> directory could look like this:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>|-defaults
+|---es.rb
+|---en.rb
+|-models
+|---book
+|-----es.rb
+|-----en.rb
+|-views
+|---defaults
+|-----es.rb
+|-----en.rb
+|---books
+|-----es.rb
+|-----en.rb
+|---users
+|-----es.rb
+|-----en.rb
+|---navigation
+|-----es.rb
+|-----en.rb</tt></pre>
+</div></div>
+<div class="paragraph"><p>This way, you can separate model and model attribute names from text inside views, and all of this from the "defaults" (eg. date and time formats).</p></div>
+<div class="paragraph"><p>Other stores for the i18n library could provide different means of such separation.</p></div>
+<div class="paragraph"><p>Do check the <a href="http://rails-i18n.org/wiki">Rails i18n Wiki</a> for list of tools available for managing translations.</p></div>
</div>
<h2 id="_overview_of_the_i18n_api_features">4. Overview of the I18n API features</h2>
<div class="sectionbody">
-<div class="paragraph"><p>The following purposes are covered:</p></div>
+<div class="paragraph"><p>You should have good understanding of using the i18n library now, knowing all neccessary aspects of internationalizing a basic Rails application. In the following chapters, we&#8217;ll cover it&#8217;s features in more depth.</p></div>
+<div class="paragraph"><p>Covered are features like these:</p></div>
<div class="ulist"><ul>
<li>
<p>
-lookup translations
+looking up translations
</p>
</li>
<li>
<p>
-interpolate data into translations
+interpolating data into translations
</p>
</li>
<li>
<p>
-pluralize translations
+pluralizing translations
</p>
</li>
<li>
<p>
-localize dates, numbers, currency etc.
+localizing dates, numbers, currency etc.
</p>
</li>
</ul></div>
@@ -547,14 +698,14 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>I18n<span style="color: #990000">.</span>t <span style="color: #990000">:</span>message
I18n<span style="color: #990000">.</span>t <span style="color: #FF0000">'message'</span></tt></pre></div></div>
-<div class="paragraph"><p>translate also takes a :scope option which can contain one or many additional keys that will be used to specify a “namespace” or scope for a translation key:</p></div>
+<div class="paragraph"><p><tt>translate</tt> also takes a <tt>:scope</tt> option which can contain one or many additional keys that will be used to specify a “namespace” or scope for a translation key:</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>I18n<span style="color: #990000">.</span>t <span style="color: #990000">:</span>invalid<span style="color: #990000">,</span> <span style="color: #990000">:</span>scope <span style="color: #990000">=&gt;</span> <span style="color: #990000">[:</span>active_record<span style="color: #990000">,</span> <span style="color: #990000">:</span>error_messages<span style="color: #990000">]</span></tt></pre></div></div>
-<div class="paragraph"><p>This looks up the :invalid message in the Active Record error messages.</p></div>
+<div class="paragraph"><p>This looks up the <tt>:invalid</tt> message in the Active Record error messages.</p></div>
<div class="paragraph"><p>Additionally, both the key and scopes can be specified as dot separated keys as in:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
@@ -582,7 +733,7 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt>I18n<span style="color: #990000">.</span>t <span style="color: #990000">:</span>missing<span style="color: #990000">,</span> <span style="color: #990000">:</span>default <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Not here'</span>
<span style="font-style: italic"><span style="color: #9A1900"># =&gt; 'Not here'</span></span></tt></pre></div></div>
<div class="paragraph"><p>If the default value is a Symbol it will be used as a key and translated. One can provide multiple values as default. The first one that results in a value will be returned.</p></div>
-<div class="paragraph"><p>E.g. the following first tries to translate the key :missing and then the key :also_missing. As both do not yield a result the string "Not here" will be returned:</p></div>
+<div class="paragraph"><p>E.g. the following first tries to translate the key <tt>:missing</tt> and then the key <tt>:also_missing.</tt> As both do not yield a result the string "Not here" will be returned:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -608,8 +759,8 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt>I18n<span style="color: #990000">.</span>t <span style="color: #FF0000">'active_record.error_messages'</span>
<span style="font-style: italic"><span style="color: #9A1900"># =&gt; { :inclusion =&gt; "is not included in the list", :exclusion =&gt; ... }</span></span></tt></pre></div></div>
<h3 id="_interpolation">4.2. Interpolation</h3>
-<div class="paragraph"><p>In many cases you want to abstract your translations so that variables can be interpolated into the translation. For this reason the I18n API provides an interpolation feature.</p></div>
-<div class="paragraph"><p>All options besides :default and :scope that are passed to #translate will be interpolated to the translation:</p></div>
+<div class="paragraph"><p>In many cases you want to abstract your translations so that <strong>variables can be interpolated into the translation</strong>. For this reason the I18n API provides an interpolation feature.</p></div>
+<div class="paragraph"><p>All options besides <tt>:default</tt> and <tt>:scope</tt> that are passed to <tt>#translate</tt> will be interpolated to the translation:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -618,10 +769,10 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt>I18n<span style="color: #990000">.</span>backend<span style="color: #990000">.</span>store_translations <span style="color: #990000">:</span>en<span style="color: #990000">,</span> <span style="color: #990000">:</span>thanks <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Thanks {{name}}!'</span>
I18n<span style="color: #990000">.</span>translate <span style="color: #990000">:</span>thanks<span style="color: #990000">,</span> <span style="color: #990000">:</span>name <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'Jeremy'</span>
<span style="font-style: italic"><span style="color: #9A1900"># =&gt; 'Thanks Jeremy!'</span></span></tt></pre></div></div>
-<div class="paragraph"><p>If a translation uses :default or :scope as a interpolation variable an I18n::ReservedInterpolationKey exception is raised. If a translation expects an interpolation variable but it has not been passed to #translate an I18n::MissingInterpolationArgument exception is raised.</p></div>
+<div class="paragraph"><p>If a translation uses <tt>:default</tt> or <tt>:scope</tt> as a interpolation variable an I+18n::ReservedInterpolationKey+ exception is raised. If a translation expects an interpolation variable but it has not been passed to <tt>#translate</tt> an <tt>I18n::MissingInterpolationArgument</tt> exception is raised.</p></div>
<h3 id="_pluralization">4.3. Pluralization</h3>
<div class="paragraph"><p>In English there&#8217;s only a singular and a plural form for a given string, e.g. "1 message" and "2 messages". Other languages (<a href="http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html#ar">Arabic</a>, <a href="http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html#ja">Japanese</a>, <a href="http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html#ru">Russian</a> and many more) have different grammars that have additional or less <a href="http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html">plural forms</a>. Thus, the I18n API provides a flexible pluralization feature.</p></div>
-<div class="paragraph"><p>The :count interpolation variable has a special role in that it both is interpolated to the translation and used to pick a pluralization from the translations according to the pluralization rules defined by CLDR:</p></div>
+<div class="paragraph"><p>The <tt>:count</tt> interpolation variable has a special role in that it both is interpolated to the translation and used to pick a pluralization from the translations according to the pluralization rules defined by CLDR:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -633,18 +784,18 @@ http://www.gnu.org/software/src-highlite -->
<span style="color: #FF0000">}</span>
I18n<span style="color: #990000">.</span>translate <span style="color: #990000">:</span>inbox<span style="color: #990000">,</span> <span style="color: #990000">:</span>count <span style="color: #990000">=&gt;</span> <span style="color: #993399">2</span>
<span style="font-style: italic"><span style="color: #9A1900"># =&gt; '2 messages'</span></span></tt></pre></div></div>
-<div class="paragraph"><p>The algorithm for pluralizations in :en is as simple as:</p></div>
+<div class="paragraph"><p>The algorithm for pluralizations in <tt>:en</tt> is as simple 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>entry<span style="color: #990000">[</span>count <span style="color: #990000">==</span> <span style="color: #993399">1</span> <span style="color: #990000">?</span> <span style="color: #993399">0</span> <span style="color: #990000">:</span> <span style="color: #993399">1</span><span style="color: #990000">]</span></tt></pre></div></div>
-<div class="paragraph"><p>I.e. the translation denoted as :one is regarded as singular, the other is used as plural (including the count being zero).</p></div>
-<div class="paragraph"><p>If the lookup for the key does not return an Hash suitable for pluralization an I18n::InvalidPluralizationData exception is raised.</p></div>
+<div class="paragraph"><p>I.e. the translation denoted as <tt>:one</tt> is regarded as singular, the other is used as plural (including the count being zero).</p></div>
+<div class="paragraph"><p>If the lookup for the key does not return an Hash suitable for pluralization an <tt>18n::InvalidPluralizationData</tt> exception is raised.</p></div>
<h3 id="_setting_and_passing_a_locale">4.4. Setting and passing a locale</h3>
-<div class="paragraph"><p>The locale can be either set pseudo-globally to I18n.locale (which uses Thread.current like, e.g., Time.zone) or can be passed as an option to #translate and #localize.</p></div>
-<div class="paragraph"><p>If no locale is passed I18n.locale is used:</p></div>
+<div class="paragraph"><p>The locale can be either set pseudo-globally to <tt>I18n.locale</tt> (which uses <tt>Thread.current</tt> like, e.g., <tt>Time.zone</tt>) or can be passed as an option to <tt>#translate</tt> and <tt>#localize</tt>.</p></div>
+<div class="paragraph"><p>If no locale is passed <tt>I18n.locale</tt> is used:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -661,7 +812,7 @@ http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt>I18n<span style="color: #990000">.</span>t <span style="color: #990000">:</span>foo<span style="color: #990000">,</span> <span style="color: #990000">:</span>locale <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>de
I18n<span style="color: #990000">.</span>l Time<span style="color: #990000">.</span>now<span style="color: #990000">,</span> <span style="color: #990000">:</span>locale <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>de</tt></pre></div></div>
-<div class="paragraph"><p>I18n.locale defaults to I18n.default_locale which defaults to :en. The default locale can be set like this:</p></div>
+<div class="paragraph"><p><tt>I18n.locale</tt> defaults to <tt>I18n.default_locale</tt> which defaults to :<tt>en</tt>. The default locale can be set like this:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -694,8 +845,8 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt>pt<span style="color: #990000">:</span>
foo<span style="color: #990000">:</span>
bar<span style="color: #990000">:</span> baz</tt></pre></div></div>
-<div class="paragraph"><p>As you see in both cases the toplevel key is the locale. :foo is a namespace key and :bar is the key for the translation "baz".</p></div>
-<div class="paragraph"><p>Here is a "real" example from the ActiveSupport en.yml translations YAML file:</p></div>
+<div class="paragraph"><p>As you see in both cases the toplevel key is the locale. <tt>:foo</tt> is a namespace key and <tt>:bar</tt> is the key for the translation "baz".</p></div>
+<div class="paragraph"><p>Here is a "real" example from the ActiveSupport <tt>en.yml</tt> translations YAML file:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -707,7 +858,7 @@ http://www.gnu.org/software/src-highlite -->
default<span style="color: #990000">:</span> <span style="color: #FF0000">"%Y-%m-%d"</span>
short<span style="color: #990000">:</span> <span style="color: #FF0000">"%b %d"</span>
long<span style="color: #990000">:</span> <span style="color: #FF0000">"%B %d, %Y"</span></tt></pre></div></div>
-<div class="paragraph"><p>So, all of the following equivalent lookups will return the :short date format "%B %d":</p></div>
+<div class="paragraph"><p>So, all of the following equivalent lookups will return the <tt>:short</tt> date format <tt>"%B %d"</tt>:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -717,9 +868,9 @@ http://www.gnu.org/software/src-highlite -->
I18n<span style="color: #990000">.</span>t <span style="color: #FF0000">'formats.short'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>scope <span style="color: #990000">=&gt;</span> <span style="color: #990000">:</span>date
I18n<span style="color: #990000">.</span>t <span style="color: #990000">:</span>short<span style="color: #990000">,</span> <span style="color: #990000">:</span>scope <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'date.formats'</span>
I18n<span style="color: #990000">.</span>t <span style="color: #990000">:</span>short<span style="color: #990000">,</span> <span style="color: #990000">:</span>scope <span style="color: #990000">=&gt;</span> <span style="color: #990000">[:</span>date<span style="color: #990000">,</span> <span style="color: #990000">:</span>formats<span style="color: #990000">]</span></tt></pre></div></div>
-<div class="paragraph"><p>Generally we recommend using YAML as a format for storing translations. There are cases though where you want to store Ruby lambdas as part of your locale data, e.g. for special date</p></div>
+<div class="paragraph"><p>Generally we recommend using YAML as a format for storing translations. There are cases though where you want to store Ruby lambdas as part of your locale data, e.g. for special date.</p></div>
<h3 id="_translations_for_active_record_models">5.1. Translations for Active Record models</h3>
-<div class="paragraph"><p>You can use the methods Model.human_name and Model.human_attribute_name(attribute) to transparently lookup translations for your model and attribute names.</p></div>
+<div class="paragraph"><p>You can use the methods <tt>Model.human_name</tt> and <tt>Model.human_attribute_name(attribute)</tt> to transparently lookup translations for your model and attribute names.</p></div>
<div class="paragraph"><p>For example when you add the following translations:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
@@ -734,11 +885,11 @@ http://www.gnu.org/software/src-highlite -->
user<span style="color: #990000">:</span>
login<span style="color: #990000">:</span> <span style="color: #FF0000">"Handle"</span>
<span style="font-style: italic"><span style="color: #9A1900"># will translate User attribute "login" as "Handle"</span></span></tt></pre></div></div>
-<div class="paragraph"><p>Then User.human_name will return "Dude" and User.human_attribute_name(:login) will return "Handle".</p></div>
+<div class="paragraph"><p>Then <tt>User.human_name</tt> will return "Dude" and <tt>User.human_attribute_name(:login)</tt> will return "Handle".</p></div>
<h4 id="_error_message_scopes">5.1.1. Error message scopes</h4>
<div class="paragraph"><p>Active Record validation error messages can also be translated easily. Active Record gives you a couple of namespaces where you can place your message translations in order to provide different messages and translation for certain models, attributes and/or validations. It also transparently takes single table inheritance into account.</p></div>
<div class="paragraph"><p>This gives you quite powerful means to flexibly adjust your messages to your application&#8217;s needs.</p></div>
-<div class="paragraph"><p>Consider a User model with a validates_presence_of validation for the name attribute like this:</p></div>
+<div class="paragraph"><p>Consider a User model with a <tt>validates_presence_of</tt> validation for the name attribute like this:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -747,7 +898,7 @@ http://www.gnu.org/software/src-highlite -->
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> User <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
validates_presence_of <span style="color: #990000">:</span>name
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span></tt></pre></div></div>
-<div class="paragraph"><p>The key for the error message in this case is :blank. Active Record will lookup this key in the namespaces:</p></div>
+<div class="paragraph"><p>The key for the error message in this case is <tt>:blank</tt>. Active Record will lookup this key in the namespaces:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -788,9 +939,9 @@ activerecord<span style="color: #990000">.</span>errors<span style="color: #9900
activerecord<span style="color: #990000">.</span>errors<span style="color: #990000">.</span>messages<span style="color: #990000">.</span>blank</tt></pre></div></div>
<div class="paragraph"><p>This way you can provide special translations for various error messages at different points in your models inheritance chain and in the attributes, models or default scopes.</p></div>
<h4 id="_error_message_interpolation">5.1.2. Error message interpolation</h4>
-<div class="paragraph"><p>The translated model name and translated attribute name are always available for interpolation.</p></div>
+<div class="paragraph"><p>The translated model name, translated attribute name, and value are always available for interpolation.</p></div>
<div class="paragraph"><p></p></div>
-<div class="paragraph"><p>count and/or value are available where applicable. Count can be used for pluralization if present:</p></div>
+<div class="paragraph"><p><tt>count</tt>, where available, can be used for pluralization if present:</p></div>
<div class="tableblock">
<table rules="all"
width="100%"
@@ -859,85 +1010,85 @@ cellspacing="0" cellpadding="4">
<td align="left"><p class="table">validates_uniqueness_of</p></td>
<td align="left"><p class="table">-</p></td>
<td align="left"><p class="table">:taken</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">-</p></td>
</tr>
<tr>
<td align="left"><p class="table">validates_format_of</p></td>
<td align="left"><p class="table">-</p></td>
<td align="left"><p class="table">:invalid</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">-</p></td>
</tr>
<tr>
<td align="left"><p class="table">validates_inclusion_of</p></td>
<td align="left"><p class="table">-</p></td>
<td align="left"><p class="table">:inclusion</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">-</p></td>
</tr>
<tr>
<td align="left"><p class="table">validates_exclusion_of</p></td>
<td align="left"><p class="table">-</p></td>
<td align="left"><p class="table">:exclusion</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">-</p></td>
</tr>
<tr>
<td align="left"><p class="table">validates_associated</p></td>
<td align="left"><p class="table">-</p></td>
<td align="left"><p class="table">:invalid</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">-</p></td>
</tr>
<tr>
<td align="left"><p class="table">validates_numericality_of</p></td>
<td align="left"><p class="table">-</p></td>
<td align="left"><p class="table">:not_a_number</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">-</p></td>
</tr>
<tr>
<td align="left"><p class="table">validates_numericality_of</p></td>
<td align="left"><p class="table">:greater_than</p></td>
<td align="left"><p class="table">:greater_than</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">count</p></td>
</tr>
<tr>
<td align="left"><p class="table">validates_numericality_of</p></td>
<td align="left"><p class="table">:greater_than_or_equal_to</p></td>
<td align="left"><p class="table">:greater_than_or_equal_to</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">count</p></td>
</tr>
<tr>
<td align="left"><p class="table">validates_numericality_of</p></td>
<td align="left"><p class="table">:equal_to</p></td>
<td align="left"><p class="table">:equal_to</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">count</p></td>
</tr>
<tr>
<td align="left"><p class="table">validates_numericality_of</p></td>
<td align="left"><p class="table">:less_than</p></td>
<td align="left"><p class="table">:less_than</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">count</p></td>
</tr>
<tr>
<td align="left"><p class="table">validates_numericality_of</p></td>
<td align="left"><p class="table">:less_than_or_equal_to</p></td>
<td align="left"><p class="table">:less_than_or_equal_to</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">count</p></td>
</tr>
<tr>
<td align="left"><p class="table">validates_numericality_of</p></td>
<td align="left"><p class="table">:odd</p></td>
<td align="left"><p class="table">:odd</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">-</p></td>
</tr>
<tr>
<td align="left"><p class="table">validates_numericality_of</p></td>
<td align="left"><p class="table">:even</p></td>
<td align="left"><p class="table">:even</p></td>
-<td align="left"><p class="table">value</p></td>
+<td align="left"><p class="table">-</p></td>
</tr>
</tbody>
</table>
</div>
<h4 id="_translations_for_the_active_record_error_messages_for_helper">5.1.3. Translations for the Active Record error_messages_for helper</h4>
-<div class="paragraph"><p>If you are using the Active Record error_messages_for helper you will want to add translations for it.</p></div>
+<div class="paragraph"><p>If you are using the Active Record <tt>error_messages_for</tt> helper you will want to add translations for it.</p></div>
<div class="paragraph"><p>Rails ships with the following translations:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
@@ -958,17 +1109,17 @@ http://www.gnu.org/software/src-highlite -->
<div class="ulist"><ul>
<li>
<p>
-distance_of_time_in_words translates and pluralizes its result and interpolates the number of seconds, minutes, hours and so on. See <a href="http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L51">datetime.distance_in_words</a> translations.
+<tt>distance_of_time_in_words</tt> translates and pluralizes its result and interpolates the number of seconds, minutes, hours and so on. See <a href="http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L51">datetime.distance_in_words</a> translations.
</p>
</li>
<li>
<p>
-datetime_select and select_month use translated month names for populating the resulting select tag. See <a href="http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L15">date.month_names</a> for translations. datetime_select also looks up the order option from <a href="http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L18">date.order</a> (unless you pass the option explicitely). All date select helpers translate the prompt using the translations in the <a href="http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L83">datetime.prompts</a> scope if applicable.
+<tt>datetime_select</tt> and <tt>select_month</tt> use translated month names for populating the resulting select tag. See <a href="http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L15">date.month_names</a> for translations. <tt>datetime_select</tt> also looks up the order option from <a href="http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L18">date.order</a> (unless you pass the option explicitely). All date select helpers translate the prompt using the translations in the <a href="http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L83">datetime.prompts</a> scope if applicable.
</p>
</li>
<li>
<p>
-The number_to_currency, number_with_precision, number_to_percentage, number_with_delimiter and humber_to_human_size helpers use the number format settings located in the <a href="http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L2">number</a> scope.
+The <tt>number_to_currency</tt>, <tt>number_with_precision</tt>, <tt>number_to_percentage</tt>, <tt>number_with_delimiter</tt> and <tt>humber_to_human_size</tt> helpers use the number format settings located in the <a href="http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L2">number</a> scope.
</p>
</li>
</ul></div>
@@ -976,25 +1127,21 @@ The number_to_currency, number_with_precision, number_to_percentage, number_with
<div class="ulist"><ul>
<li>
<p>
-human_name and human_attribute_name use translations for model names and attribute names if available in the <a href="http://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml#L43">activerecord.models</a> scope. They also support translations for inherited class names (e.g. for use with STI) as explained above in "Error message scopes".
-</p>
-</li>
-<li>
-<p>
-ActiveRecord::Errors#generate_message (which is used by Active Record validations but may also be used manually) uses human_name and human_attribute_name (see above). It also translates the error message and supports translations for inherited class names as explained above in "Error message scopes".
+<tt>human_name</tt> and <tt>human_attribute_name</tt> use translations for model names and attribute names if available in the <a href="http://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml#L43">activerecord.models</a> scope. They also support translations for inherited class names (e.g. for use with STI) as explained above in "Error message scopes".
</p>
</li>
<li>
<p>
-ActiveRecord::Errors#full_messages prepends the attribute name to the error message using a separator that will be looked up from <a href="http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L91">activerecord.errors.format.separator</a> (and defaults to ' ').
+<tt>ActiveRecord::Errors#generate_message</tt> (which is used by Active Record validations but may also be used manually) uses <tt>human_name</tt> and <tt>human_attribute_name</tt> (see above). It also translates the error message and supports translations for inherited class names as explained above in "Error message scopes".
</p>
</li>
</ul></div>
+<div class="paragraph"><p>*<tt> ActiveRecord::Errors#full_messages</tt> prepends the attribute name to the error message using a separator that will be looked up from <a href="http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L91">activerecord.errors.format.separator</a> (and defaults to <tt>' '</tt>).</p></div>
<h4 id="_activesupport_methods">5.2.3. ActiveSupport methods</h4>
<div class="ulist"><ul>
<li>
<p>
-Array#to_sentence uses format settings as given in the <a href="http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L30">support.array</a> scope.
+<tt>Array#to_sentence</tt> uses format settings as given in the <a href="http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L30">support.array</a> scope.
</p>
</li>
</ul></div>
@@ -1023,7 +1170,7 @@ InvalidPluralizationData <span style="font-style: italic"><span style="color
MissingInterpolationArgument <span style="font-style: italic"><span style="color: #9A1900"># the translation expects an interpolation argument that has not been passed</span></span>
ReservedInterpolationKey <span style="font-style: italic"><span style="color: #9A1900"># the translation contains a reserved interpolation variable name (i.e. one of: scope, default)</span></span>
UnknownFileType <span style="font-style: italic"><span style="color: #9A1900"># the backend does not know how to handle a file type that was added to I18n.load_path</span></span></tt></pre></div></div>
-<div class="paragraph"><p>The I18n API will catch all of these exceptions when they were thrown in the backend and pass them to the default_exception_handler method. This method will re-raise all exceptions except for MissingTranslationData exceptions. When a MissingTranslationData exception has been caught it will return the exception’s error message string containing the missing key/scope.</p></div>
+<div class="paragraph"><p>The I18n API will catch all of these exceptions when they were thrown in the backend and pass them to the default_exception_handler method. This method will re-raise all exceptions except for <tt>MissingTranslationData</tt> exceptions. When a <tt>MissingTranslationData</tt> exception has been caught it will return the exception’s error message string containing the missing key/scope.</p></div>
<div class="paragraph"><p>The reason for this is that during development you&#8217;d usually want your views to still render even though a translation is missing.</p></div>
<div class="paragraph"><p>In other contexts you might want to change this behaviour though. E.g. the default exception handling does not allow to catch missing translations during automated tests easily. For this purpose a different exception handler can be specified. The specified exception handler must be a method on the I18n module:</p></div>
<div class="listingblock">
@@ -1038,9 +1185,9 @@ http://www.gnu.org/software/src-highlite -->
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
I18n<span style="color: #990000">.</span>exception_handler <span style="color: #990000">=</span> <span style="color: #990000">:</span>just_raise_that_exception</tt></pre></div></div>
-<div class="paragraph"><p>This would re-raise all caught exceptions including MissingTranslationData.</p></div>
-<div class="paragraph"><p>Another example where the default behaviour is less desirable is the Rails TranslationHelper which provides the method #t (as well as #translate). When a MissingTranslationData exception occurs in this context the helper wraps the message into a span with the css class translation_missing.</p></div>
-<div class="paragraph"><p>To do so the helper forces I18n#translate to raise exceptions no matter what exception handler is defined by setting the :raise option:</p></div>
+<div class="paragraph"><p>This would re-raise all caught exceptions including <tt>MissingTranslationData</tt>.</p></div>
+<div class="paragraph"><p>Another example where the default behaviour is less desirable is the Rails TranslationHelper which provides the method <tt>#t</tt> (as well as <tt>#translate</tt>). When a <tt>MissingTranslationData</tt> exception occurs in this context the helper wraps the message into a span with the CSS class <tt>translation_missing</tt>.</p></div>
+<div class="paragraph"><p>To do so the helper forces <tt>I18n#translate</tt> to raise exceptions no matter what exception handler is defined by setting the <tt>:raise</tt> option:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1057,7 +1204,7 @@ http://www.gnu.org/software/src-highlite -->
<div class="sectionbody">
<div class="paragraph"><p>I18n support in Ruby on Rails was introduced in the release 2.2 and is still evolving. The project follows the good Ruby on Rails development tradition of evolving solutions in plugins and real applications first and then cherry-picking the best bread of most widely useful features second for inclusion to the core.</p></div>
<div class="paragraph"><p>Thus we encourage everybody to experiment with new ideas and features in plugins or other libraries and make them available to the community. (Don&#8217;t forget to announce your work on our <a href="http://groups.google.com/group/rails-i18n">mailinglist</a>!)</p></div>
-<div class="paragraph"><p>If you find your own locale (language) missing from our <a href="http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale">example translations data</a> repository for Ruby on Rails</p></div>
+<div class="paragraph"><p>If you find your own locale (language) missing from our <a href="http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale">example translations data</a> repository for Ruby on Rails, please <a href="http://github.com/guides/fork-a-project-and-submit-your-modifications"><em>fork</em></a> the repository, add your data and send a <a href="http://github.com/guides/pull-requests">pull request</a>.</p></div>
</div>
<h2 id="_resources">9. Resources</h2>
<div class="sectionbody">
@@ -1069,7 +1216,7 @@ http://www.gnu.org/software/src-highlite -->
</li>
<li>
<p>
-<a href="http://groups.google.com/group/rails-i18n">rails-i18n Google group</a> - The project&#8217;s mailinglist.
+<a href="http://groups.google.com/group/rails-i18n">rails-i18n Google group</a> - The project&#8217;s mailing list.
</p>
</li>
<li>
@@ -1099,12 +1246,12 @@ http://www.gnu.org/software/src-highlite -->
<div class="ulist"><ul>
<li>
<p>
-Sven Fuchs[http://www.workingwithrails.com/person/9963-sven-fuchs] (initial author)
+<a href="http://www.workingwithrails.com/person/9963-sven-fuchs">Sven Fuchs</a> (initial author)
</p>
</li>
<li>
<p>
-Karel Minarik[http://www.workingwithrails.com/person/7476-karel-mina-k]
+<a href="http://www.workingwithrails.com/person/7476-karel-mina-k">Karel Minařík</a>
</p>
</li>
</ul></div>
diff --git a/railties/doc/guides/html/index.html b/railties/doc/guides/html/index.html
index d7079c9393..16ce603cec 100644
--- a/railties/doc/guides/html/index.html
+++ b/railties/doc/guides/html/index.html
@@ -136,20 +136,20 @@ understand how to use routing in your own Rails applications, start here.</p></d
<div class="sidebar-title"><a href="actioncontroller_basics.html">Basics of Action Controller</a></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>
+<h2>Digging Deeper</h2>
<div class="sidebarblock">
<div class="sidebar-content">
-<div class="sidebar-title"><a href="caching_with_rails.html">Rails Caching</a></div>
+<div class="sidebar-title"><a href="action_mailer_basics.html">Action Mailer Basics</a></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/caution.png" alt="Caution" />
</td>
-<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/10">Lighthouse Ticket</a></td>
+<td class="content"><a href="http://rails.lighthouseapp.com/projects/16213/tickets/25">Lighthouse ticket</a></td>
</tr></table>
</div>
-<div class="paragraph"><p>This guide covers the three types of caching that Rails provides by default.</p></div>
+<div class="paragraph"><p>This guide describes how to use Action Mailer to send and receive emails.</p></div>
</div></div>
-<h2>Digging Deeper</h2>
<div class="sidebarblock">
<div class="sidebar-content">
<div class="sidebar-title"><a href="testing_rails_applications.html">Testing Rails Applications</a></div>
@@ -212,7 +212,7 @@ of your code.</p></div>
<div class="paragraph"><p>This guide covers the command line tools and rake tasks provided by Rails.</p></div>
</div></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 class="paragraph"><p>This work is licensed under a <a href="http://creativecommons.org/licenses/by-sa/3.0">Creative Commons Attribution-Share Alike 3.0 License</a></p></div>
</div>
</div>
diff --git a/railties/doc/guides/source/2_3_release_notes.txt b/railties/doc/guides/source/2_3_release_notes.txt
new file mode 100644
index 0000000000..08d591d149
--- /dev/null
+++ b/railties/doc/guides/source/2_3_release_notes.txt
@@ -0,0 +1,399 @@
+Ruby on Rails 2.3 Release Notes
+===============================
+
+Rails 2.3 delivers a variety of new and improved features, including pervasive Rack integration, refreshed support for Rails Engines, nested transactions for Active Record, dynamic and default scopes, unified rendering, more efficient routing, application templates, and quiet backtraces. 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 link:http://github.com/rails/rails/commits/master[list of commits] in the main Rails repository on GitHub.
+
+== Application Architecture
+
+There are two major changes in the architecture of Rails applications: complete integration of the link:http://rack.rubyforge.org/[Rack] modular web server interface, and renewed support for Rails Engines.
+
+=== Rack Integration
+
+Rails has now broken with its CGI past, and uses Rack everywhere. This required and resulted in a tremendous number of internal changes (but if you use CGI, don't worry; Rails now supports CGI through a proxy interface.) Still, this is a major change to Rails internals. After upgrading to 2.3, you should test on your local environment and your production environment. Some things to test:
+
+* Sessions
+* Cookies
+* File uploads
+* JSON/XML APIs
+
+Here's a summary of the rack-related changes:
+
+* +script/server+ has been switched to use Rack, which means it supports any Rack compatible server. +script/server+ will also pick up a rackup configuration file if one exists. By default, it will look for a +config.ru+ file, but you can override this with the +-c+ switch.
+* The FCGI handler goes through Rack
+* ActionController::Dispatcher maintains its own default middleware stack. Middlewares can be injected in, reordered, and removed. The stack is compiled into a chain on boot. You can configure the middleware stack in +environment.rb+
+* The +rake middleware+ task has been added to inspect the middleware stack. This is useful for debugging the order of the middleware stack.
+* The integration test runner has been modified to execute the entire middleware and application stack. This makes integration tests perfect for testing Rack middleware.
+* +ActionController::CGIHandler+ is a backwards compatible CGI wrapper around Rack. The +CGIHandler+ is meant to take an old CGI object and converts its environment information into a Rack compatible form.
+* +CgiRequest+ and +CgiResponse+ have been removed
+* Session stores are now lazy loaded. If you never access the session object during a request, it will never attempt to load the session data (parse the cookie, load the data from memcache, or lookup an Active Record object).
+* +CGI::Session::CookieStore+ has been replaced by +ActionController::Session::CookieStore+
+* +CGI::Session::MemCacheStore+ has been replaced by +ActionController::Session::MemCacheStore+
+* +CGI::Session::ActiveRecordStore+ has been replaced by +ActiveRecord::SessionStore+
+* You can still change your session store with +ActionController::Base.session_store = :active_record_store+
+* Default sessions options are still set with +ActionController::Base.session = { :key => "..." }+
+* The mutex that normally wraps your entire request has been moved into middleware, +ActionController::Lock+
+* +ActionController::AbstractRequest+ and +ActionController::Request+ have been unified. The new +ActionController::Request+ inherits from +Rack::Request+. This affects access to +response.headers['type']+ in test requests. Use +response.content_type+ instead.
+* +ActiveRecord::QueryCache+ middleware is automatically inserted onto the middleware stack if +ActiveRecord+ has been loaded. This middleware sets up and flushes the per-request Active Record query cache.
+* The Rails router and controller classes follow the Rack spec. You can call a controller directly with +SomeController.call(env)+. The router stores the routing parameters in +rack.routing_args+.
+* +ActionController::Request+ inherits from +Rack::Request+
+* Instead of +config.action_controller.session = { :session_key => 'foo', ...+ use +config.action_controller.session = { :key => 'foo', ...+
+* Using the +ParamsParser+ middleware preprocesses any XML, JSON, or YAML requests so they can be read normally with any +Rack::Request+ object after it.
+
+=== Renewed Support for Rails Engines
+
+After some versions without an upgrade, Rails 2.3 offers some new features for Rails Engines (Rails applications that can be embedded within other applications). First, routing files in engines are automatically loaded and reloaded now, just like your +routes.rb+ file (this also applies to routing files in other plugins). Second, if your plugin has an app folder, then app/[models|controllers|helpers] will automatically be added to the Rails load path. Engines also support adding view paths now.
+
+* Lead Contributor: link:http://www.loudthinking.com/[David Heinemeier Hansson]
+
+== Documentation
+
+The link:http://guides.rubyonrails.org/[Ruby on Rails guides] project has published several additional guides for Rails 2.3. In addition, a link:http://guides.rails.info/[separate site] maintains updated copies of the Guides for Edge Rails. Other documentation efforts include a relaunch of the link:http://newwiki.rubyonrails.org/[Rails wiki] and early planning for a Rails Book.
+
+* More Information: link:http://weblog.rubyonrails.org/2009/1/15/rails-documentation-projects[Rails Documentation Projects]
+
+== Active Record
+
+Active Record gets quite a number of new features and bug fixes in Rails 2.3. The highlights include nested transactions, dynamic scopes, and default scopes.
+
+=== Nested Transactions
+
+Active Record now supports nested transactions, a much-requested feature. Now you can write code like this:
+
+[source, ruby]
+-------------------------------------------------------
+User.transaction do
+ User.create(:username => 'Admin')
+ User.transaction(:requires_new => true) do
+ User.create(:username => 'Regular')
+ raise ActiveRecord::Rollback
+ end
+ end
+
+ User.find(:all) # => Returns only Admin
+-------------------------------------------------------
+
+Nested transactions let you roll back an inner transaction without affecting the state of the outer transaction. If you want a transaction to be nested, you must explicitly add the +:requires_new+ option; otherwise, a nested transaction simply becomes part of the parent transaction (as it does currently on Rails 2.2). Under the covers, nested transactions are link:http://rails.lighthouseapp.com/projects/8994/tickets/383[using savepoints], so they're supported even on databases that don't have true nested transactions. There is also a bit of magic going on to make these transactions play well with transactional fixtures during testing.
+
+* Lead Contributors: link:http://www.workingwithrails.com/person/4985-jonathan-viney[Jonathan Viney] and link:http://izumi.plan99.net/blog/[Hongli Lai]
+
+=== Dynamic Scopes
+
+You know about dynamic finders in Rails (which allow you to concoct methods like +find_by_color_and_flavor+ on the fly) and named scopes (which allow you to encapsulate reusable query conditions into friendly names like +currently_active+). Well, now you can have dynamic scope methods. The idea is to put together syntax that allows filtering on the fly <i>and</i> method chaining. For example:
+
+[source, ruby]
+-------------------------------------------------------
+Order.scoped_by_customer_id(12)
+Order.scoped_by_customer_id(12).find(:all,
+ :conditions => "status = 'open'")
+Order.scoped_by_customer_id(12).scoped_by_status("open")
+-------------------------------------------------------
+
+There's nothing to define to use dynamic scopes: they just work.
+
+* Lead Contributor: link:http://evilmartians.com/[Yaroslav Markin]
+* More Information: link:http://ryandaigle.com/articles/2008/12/29/what-s-new-in-edge-rails-dynamic-scope-methods[What's New in Edge Rails: Dynamic Scope Methods].
+
+=== Default Scopes
+
+Rails 2.3 will introduce the notion of _default scopes_ similar to named scopes, but applying to all named scopes or find methods within the model. For example, you can write +default_scope :order => 'name ASC'+ and any time you retrieve records from that model they'll come out sorted by name (unless you override the option, of course).
+
+* Lead Contributor: Paweł Kondzior
+* More Information: link:http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping[What's New in Edge Rails: Default Scoping]
+
+=== Multiple Conditions for Callbacks
+
+When using Active Record callbacks, you can now combine +:if+ and +:unless+ options on the same callback, and supply multiple conditions as an array:
+
+[source, ruby]
+-------------------------------------------------------
+before_save :update_credit_rating, :if => :active,
+ :unless => [:admin, :cash_only]
+-------------------------------------------------------
+* Lead Contributor: L. Caviola
+
+=== Find with having
+
+Rails now has a +:having+ option on find (as well as on +has_many+ and +has_and_belongs_to_many+ associations) for filtering records in grouped finds. As those with heavy SQL backgrounds know, this allows filtering based on grouped results:
+
+[source, ruby]
+-------------------------------------------------------
+developers = Developer.find(:all, :group => "salary",
+ :having => "sum(salary) > 10000", :select => "salary")
+-------------------------------------------------------
+
+* Lead Contributor: link:http://github.com/miloops[Emilio Tagua]
+
+=== Hash Conditions for +has_many+ relationships
+
+You can once again use a hash in conditions for a +has_many+ relationship:
+
+[source, ruby]
+-------------------------------------------------------
+has_many :orders, :conditions => {:status => 'confirmed'}
+-------------------------------------------------------
+
+That worked in Rails 2.1, fails in Rails 2.2, and will now work again in Rails 2.3 (if you're dealing with this issue in Rails 2.2, you can use a string rather than a hash to specify conditions).
+
+* Lead Contributor: link:http://www.spacevatican.org/[Frederick Cheung]
+
+=== Other Active Record Changes
+
+* An extra +AS+ was removed from the code for has_and_belongs_to_many preloading, making it work better for some databases.
+* +ActiveRecord::Base#new_record?+ now returns false rather than nil when confronted with an existing record.
+* A bug in quoting table names in some +has_many :through+ associations was fixed.
+* You can now specify a particular timestamp for +updated_at+ timestamps: +cust = Customer.create(:name => "ABC Industries", :updated_at => 1.day.ago)+
+* Better error messages on failed +find_by_attribute!+ calls.
+* Active Record's +to_xml+ support gets just a little bit more flexible with the addition of a +:camelize+ option.
+* A bug in canceling callbacks from +before_update+ or +before_create_ was fixed.
+
+== Action Controller
+
+Action Controller rolls out some significant changes to rendering, as well as improvements in routing and other areas, in this release.
+
+=== Unified Rendering
+
++ActionController::Base#render+ is a lot smarter about deciding what to render. Now you can just tell it what to render and expect to get the right results. In older versions of Rails, you often need to supply explicit information to render:
+
+[source, ruby]
+-------------------------------------------------------
+render :file => '/tmp/random_file.erb'
+render :template => 'other_controller/action'
+render :action => 'show'
+-------------------------------------------------------
+
+Now in Rails 2.3, you can just supply what you want to render:
+
+[source, ruby]
+-------------------------------------------------------
+render '/tmp/random_file.erb'
+render 'other_controller/action'
+render 'show'
+render :show
+-------------------------------------------------------
+Rails chooses between file, template, and action depending on whether there is a leading slash, an embedded slash, or no slash at all in what's to be rendered. Note that you can also use a symbol instead of a string when rendering an action. Other rendering styles (+:inline, :text, :update, :nothing, :json, :xml, :js+) still require an explicit option.
+
+* Lead Contributor: link:http://m.onkey.org/[Pratik Naik]
+
+=== Application Controller Renamed
+
+If you're one of the people who has always been bothered by the special-case naming of +application.rb+, rejoice! It's been reworked to be application_controller.rb in Rails 2.3. In addition, there's a new rake task, +rake rails:update:application_controller+ to do this automatically for you - and it will be run as part of the normal +rake rails:update+ process.
+
+* Lead Contributor: link:http://www.loudthinking.com/[David Heinemeier Hansson]
+* More Information:
+ - link:http://afreshcup.com/2008/11/17/rails-2x-the-death-of-applicationrb/[The Death of Application.rb]
+ - link:http://ryandaigle.com/articles/2008/11/19/what-s-new-in-edge-rails-application-rb-duality-is-no-more[What's New in Edge Rails: Application.rb Duality is no More]
+
+=== More Efficient Routing
+
+There are a couple of significant routing changes in Rails 2.3. The +formatted_+ route helpers are gone, in favor just passing in +:format+ as an option. This cuts down the route generation process by 50% for any resource - and can save a substantial amount of memory (up to 100MB on large applications). If your code uses the +formatted_+ helpers, it will still work for the time being - but that behavior is deprecated and your application will be more efficient if you rewrite those routes using the new standard. Another big change is that Rails now supports multiple routing files, not just routes.rb. You can use +RouteSet#add_configuration_file+ to bring in more routes at any time - without clearing the currently-loaded routes. While this change is most useful for Engines, you can use it in any application that needs to load routes in batches.
+
+Lead Contributors: link:http://blog.hungrymachine.com/[Aaron Batalion] and link:http://www.loudthinking.com/[David Heinemeier Hansson]
+
+=== Rack-based Lazy-loaded Sessions
+
+A big change pushed the underpinnings of Action Controller session storage down to the Rack level. This involved a good deal of work in the code, though it should be completely transparent to your Rails applications (as a bonus, some icky patches around the old CGI session handler got removed). It's still significant, though, for one simple reason: non-Rails Rack applications have access to the same session storage handlers (and therefore the same session) as your Rails applications. In addition, sessions are now lazy-loaded (in line with the loading improvements to the rest of the framework). This means that you no longer need to explicitly disable sessions if you don't want them; just don't refer to them and they won't load.
+
+* Lead Contributor: link:http://joshpeek.com/[Josh Peek]
+
+=== MIME Type Handling Changes
+
+There are a couple of changes to the code for handling MIME types in Rails. First, +MIME::Type+ now implements the +=~+ operator, making things much cleaner when you need to check for the presence of a type that has synonyms:
+
+[source, ruby]
+-------------------------------------------------------
+if content_type && Mime::JS =~ content_type
+ # do something cool
+end
+
+Mime::JS =~ "text/javascript" => true
+Mime::JS =~ "application/javascript" => true
+-------------------------------------------------------
+
+The other change is that the framework now uses the +Mime::JS+ when checking for javascript in various spots, making it handle those alternatives cleanly.
+
+Lead Contributor: link:http://www.workingwithrails.com/person/5510-seth-fitzsimmons[Seth Fitzsimmons]
+
+=== Optimization of +respond_to+
+
+In some of the first fruits of the Rails-Merb team merger, Rails 2.3 includes some optimizations for the +respond_to+ method, which is of course heavily used in many Rails applications to allow your controller to format results differently based on the MIME type of the incoming request. After eliminating a call to +method_missing+ and some profiling and tweaking, we're seeing an 8% improvement in the number of requests per second served with a simple +respond_to+ that switches between three formats. The best part? No change at all required to the code of your application to take advantage of this speedup.
+
+* Lead Contributor: link:http://yehudakatz.com/[Yehuda Katz]
+
+=== Improved Caching Performance
+
+Rails now keeps a per-request local cache of requests, cutting down on unnecessary reads and leading to better site performance. While this work was originally limited to +MemCacheStore+, it is available to any remote store than implements the required methods.
+
+* Lead Contributor: link:http://www.motionstandingstill.com/[Nahum Wild]
+
+=== Other Action Controller Changes
+
+* ETag handling has been cleaned up a bit: Rails will now skip sending an ETag header when there's no body to the response or when sending files with +send_file+.
+* The fact that Rails checks for IP spoofing can be a nuisance for sites that do heavy traffic with cell phones, because their proxies don't generally set things up right. If that's you, you can now set +ActionController::Base.ip_spoofing_check = false+ to disable the check entirely.
+* ActionController::Dispatcher now implements its own middleware stack, which you can see by running +rake middleware+.
+* Cookie sessions now have persistent session identifiers, with API compatibility with the server-side stores.
+* You can now use symbols for the +:type+ option of +send_file+ and +send_data+, like this: +send_file("fabulous.png", :type => :png)+.
+
+== Action View
+
+Action View in Rails 2.3 picks up improvements to +render+, more flexible prompts for the date select helpers, and a speedup in asset caching, among other things.
+
+=== Smart Rendering
+
+The render method has been getting smarter over the years, and it's even smarter now. If you have an object or a collection and an appropriate partial, and the naming matches up, you can now just render the object and things will work. For example, in Rails 2.3, these render calls will work in your view (assuming sensible naming):
+
+[source, ruby]
+-------------------------------------------------------
+<% render @article %>
+<% render @articles %>
+-------------------------------------------------------
+
+* Lead Contributor: link:http://www.loudthinking.com/[David Heinemeier Hansson]
+* More Information: link:http://ryandaigle.com/articles/2008/11/20/what-s-new-in-edge-rails-render-stops-being-high-maintenance[What's New in Edge Rails: render Stops Being High-Maintenance]
+
+=== Prompts for Date Select Helpers
+
+In Rails 2.3, you can supply custom prompts for the various date select helpers (+date_select+, +time_select+, and +datetime_select+), the same way you can with collection select helpers. You can supply a prompt string or a hash of individual prompt strings for the various components. You can also just set +:prompt+ to +true+ to use the custom generic prompt:
+
+[source, ruby]
+-------------------------------------------------------
+select_datetime(DateTime.now, :prompt => true)
+
+select_datetime(DateTime.now, :prompt => "Choose date and time")
+
+select_datetime(DateTime.now, :prompt =>
+ {:day => 'Choose day', :month => 'Choose month',
+ :year => 'Choose year', :hour => 'Choose hour',
+ :minute => 'Choose minute'})
+-------------------------------------------------------
+
+Lead Contributor: link:http://samoliver.com/[Sam Oliver]
+
+=== AssetTag Timestamp Caching
+
+You're likely familiar with Rails' practice of adding timestamps to static asset paths as a "cache buster." This helps ensure that stale copies of things like images and stylesheets don't get served out of the user's browser cache when you change them on the server. You can now modify this behavior with the +cache_asset_timestamps+ configuration option for Action View. If you enable the cache, then Rails will calculate the timestamp once when it first serves an asset, and save that value. This means fewer (expensive) file system calls to serve static assets - but it also means that you can't modify any of the assets while the server is running and expect the changes to get picked up by clients.
+
+* Lead Contributor: link:http://joshpeek.com/[Josh Peek]
+
+=== Asset Hosts as Objects
+
+Asset hosts get more flexible in edge Rails with the ability to declare an asset host as a specific object that responds to a call. This allows you to to implement any complex logic you need in your asset hosting.
+
+* Lead Contributor: link:http://www.loudthinking.com/[David Heinemeier Hansson]
+* More Information: link:http://github.com/dhh/asset-hosting-with-minimum-ssl/tree/master[asset-hosting-with-minimum-ssl]
+
+=== Other Action View Changes
+
+* Token generation for CSRF protection has been simplified; now Rails uses a simple random string generated by +ActiveSupport::SecureRandom+ rather than mucking around with session IDs.
+* +auto_link+ now properly applies options (such as :target and :class) to generated e-mail links.
+* The +autolink+ helper has been refactored to make it a bit less messy and more intuitive.
+
+== Active Support
+
+Active Support has a few interesting changes, including the introduction of +Object#try+.
+
+=== Object#try
+
+A lot of folks have adopted the notion of using try() to attempt operations on objects - It's especially helpful in views where you can avoid nil-checking by writing code like +<%= @person.try(:name) %>+. Well, now it's baked right into Rails. As implemented in Rails, it raises +NoMethodError+ on private methods and always returns +nil+ if the object is nil.
+
+* Lead Contributor: link:http://m.onkey.org/[Pratik Naik]
+* More Information: link:http://ozmm.org/posts/try.html[try()].
+
+=== Object#tap Backport
+
++Object#tap+ is an addition to "Ruby 1.9":http://www.ruby-doc.org/core-1.9/classes/Object.html#M000309 and 1.8.7 that is similar to the +returning+ method that Rails has had for a while: it yields to a block, and then returns the object that was yielded. Rails now includes code to make this available under older versions of Ruby as well.
+
+Lead Contributor: link:http://bitsweat.net/[Jeremy Kemper]
+
+=== Fractional seconds for TimeWithZone
+
+The +Time+ and +TimeWithZone+ classes include an +xmlschema+ method to return the time in an XML-friendly string. As of Rails 2.3, +TimeWithZone+ supports the same argument for specifying the number of digits in the fractional second part of the returned string that +Time+ does:
+
+[source, ruby]
+-------------------------------------------------------
+>> Time.zone.now.xmlschema(6)
+=> "2009-01-16T13:00:06.13653Z"
+-------------------------------------------------------
+
+Lead Contributor: link:http://www.workingwithrails.com/person/13536-nicholas-dainty[Nicholas Dainty]
+
+=== JSON Key Quoting
+
+If you look up the spec on the "json.org" site, you'll discover that all keys in a JSON structure must be strings, and they must be quoted with double quotes. Starting with Rails 2.3, we doe the right thing here, even with numeric keys.
+
+Lead Contributor: link:http://www.koziarski.net/[Michael Koziarski]
+
+=== Other Active Support Changes
+
+* You can use +Enumerable#none?+ to check that none of the elements match the supplied block.
+* If you're using Active Support link:http://afreshcup.com/2008/10/19/coming-in-rails-22-delegate-prefixes/[delegates], the new +:allow_nil+ option lets you return nil instead of raising an exception when the target object is nil.
+* +ActiveSupport::OrderedHash+: now implements +each_key+ and +each_value+.
+* +ActiveSupport::MessageEncryptor+ provides a simple way to encrypt information for storage in an untrusted location (like cookies).
+* Active Support's +from_xml+ no longer depends on XmlSimple. Instead, Rails now includes its own XmlMini implementation, with just the functionality that it requires. This lets Rails dispense with the bundled copy of XmlSimple that it's been carting around.
+
+== Railties
+
+In addition to the Rack changes covered above, Railties (the core code of Rails itself) sports a number of significant changes, including Rails Metal, application templates, and quiet backtraces.
+
+=== Rails Metal
+
+Rails Metal is a new mechanism that provides superfast endpoints inside of your Rails applications. Metal classes bypass routing and Action Controller to give you raw speed (at the cost of all the things in Action Controller, of course). This builds on all of the recent foundation work to make Rails a Rack application with an exposed middleware stack.
+
+* Lead Contributor: link:http://www.loudthinking.com/[David Heinemeier Hansson]
+* More Information:
+ - link:http://weblog.rubyonrails.org/2008/12/17/introducing-rails-metal[Introducing Rails Metal]
+ - link:http://soylentfoo.jnewland.com/articles/2008/12/16/rails-metal-a-micro-framework-with-the-power-of-rails-m[Rails Metal: a micro-framework with the power of Rails]
+ - link:http://www.railsinside.com/deployment/180-metal-super-fast-endpoints-within-your-rails-apps.html[Metal: Super-fast Endpoints within your Rails Apps]
+ - link:http://ryandaigle.com/articles/2008/12/18/what-s-new-in-edge-rails-rails-metal[What's New in Edge Rails: Rails Metal]
+
+=== Application Templates
+
+Rails 2.3 incorporates Jeremy McAnally's "rg":http://github.com/jeremymcanally/rg/tree/master application generator. What this means is that we now have template-based application generation built right into Rails; if you have a set of plugins you include in every application (among many other use cases), you can just set up a template once and use it over and over again when you run the +rails+ command. There's also a rake task to apply a template to an existing application:
+
+[source, ruby]
+-------------------------------------------------------
+rake rails:template LOCATION=~/template.rb
+-------------------------------------------------------
+
+This will layer the changes from the template on top of whatever code the project already contains.
+
+* Lead Contributor: link:http://www.jeremymcanally.com/[Jeremy McAnally]
+* More Info:http://m.onkey.org/2008/12/4/rails-templates[Rails templates]
+
+=== Quieter Backtraces
+
+Building on Thoughtbot's "Quiet Backtrace":http://www.thoughtbot.com/projects/quietbacktrace plugin, which allows you to selectively remove lines from Test::Unit backtraces, Rails 2.3 implements +ActiveSupport::BacktraceCleaner+ and +Rails::BacktraceCleaner+ in core. This supports both filters (to perform regex-based substitutions on backtrace lines) and silencers (to remove backtrace lines entirely). Rails automatically adds silencers to get rid of the most common noise in a new application, and builds a +config/backtrace_silencers.rb+ file to hold your own additions. This feature also enables prettier printing from any gem in the backtrace.
+
+* Lead Contributor: link:http://www.loudthinking.com/[David Heinemeier Hansson]
+
+=== Faster Boot Time in Development Mode with Lazy Loading/Autoload
+
+Quite a bit of work was done to make sure that bits of Rails (and its dependencies) are only brought into memory when they're actually needed. The core frameworks - Active Support, Active Record, Action Controller, Action Mailer and Action View - are now using +autoload+ to lazy-load their individual classes. This work should help keep the memory footprint down and improve overall Rails performance.
+
+You can also specify (by using the new +preload_frameworks+ option) whether the core libraries should be autoloaded at startup. This defaults to +false+ so that Rails autoloads itself piece-by-piece, but there are some circumstances where you still need to bring in everything at once - Passenger and JRuby both want to see all of Rails loaded together.
+
+* Lead Contributors: link:http://bitsweat.net/[Jeremy Kemper] and link:http://joshpeek.com/[Josh Peek]
+
+=== Other Railties Changes
+
+* The instructions for updating a CI server to build Rails have been updated and expanded.
+* Internal Rails testing has been switched from +Test::Unit::TestCase+ to +ActiveSupport::TestCase+, and the Rails core requires Mocha to test.
+* The default +environment.rb+ file has been decluttered.
+* The dbconsole script now lets you use an all-numeric password without crashing.
+* Rails.root now returns a Pathname object, which means you can use it directly with the join method to link:http://afreshcup.com/2008/12/05/a-little-rails_root-tidiness/[clean up existing code] that uses File.join.
+* Various files in /public that deal with CGI and FCGI dispatching are no longer generated in every Rails application by default (you can still get them if you need them by adding +--with-dispatches+ when you run the rails command, or add them later with +rake rails:generate_dispatchers+).
+
+== Deprecated
+
+A few pieces of older code are deprecated in this release:
+
+* If you're one of the (fairly rare) Rails developers who deploys in a fashion that depends on the inspector, reaper, and spawner scripts, you'll need to know that those scripts are no longer included in core Rails. If you need them, you'll be able to pick up copies via the link:http://github.com/rails/irs_process_scripts/tree[irs_process_scripts] plugin.
+* +render_component+ goes from "deprecated" to "nonexistent" in Rails 2.3. If you still need it, you can install the link:http://github.com/rails/render_component/tree/master[render_component plugin].
+* Support for Rails components has been removed.
+* If you were one of the people who got used to running +script/performance/request+ to look at performance based on integration tests, you need to learn a new trick: that script has been removed from core Rails now. There’s a new request_profiler plugin that you can install to get the exact same functionality back.
+* +ActionController::Base#session_enabled?+ is deprecated because sessions are lazy-loaded now.
+* The +:digest+ and +:secret+ options to +protect_from_forgery+ are deprecated and have no effect.
+* Some integration test helpers have been removed. +response.headers["Status"]+ and +headers["Status"]+ will no longer return anything. Rack does not allow "Status" in its return headers. However you can still use the +status+ and +status_message+ helpers. +response.headers["cookie"]+ and +headers["cookie"]+ will no longer return any CGI cookies. You can inspect +headers["Set-Cookie"]+ to see the raw cookie header or use the +cookies+ helper to get a hash of the cookies sent to the client.
+
+== Credits
+
+Release notes compiled by link:http://afreshcup.com[Mike Gunderloy]
diff --git a/railties/doc/guides/source/action_mailer_basics.txt b/railties/doc/guides/source/action_mailer_basics.txt
index ac6280091b..c788e0ceab 100644
--- a/railties/doc/guides/source/action_mailer_basics.txt
+++ b/railties/doc/guides/source/action_mailer_basics.txt
@@ -342,4 +342,8 @@ class UserMailerTest < ActionMailer::TestCase
What have we done? Well, we sent the email and stored the returned object in the email variable. We then ensured that it was sent (the first assert), then, in the second batch of assertion, we ensure that the email does indeed contain the values that we expect.
== Epilogue
-This guide presented how to create a mailer and how to test it. In reality, you may find that writing your tests before you actually write your code to be a rewarding experience. It may take some time to get used to TDD (Test Driven Development), but coding this way achieves two major benefits. Firstly, you know that the code does indeed work, because the tests fail (because there's no code), then they pass, because the code that satisfies the tests was written. Secondly, when you start with the tests, you don't have to make time AFTER you write the code, to write the tests, then never get around to it. The tests are already there and testing has now become part of your coding regimen. \ No newline at end of file
+This guide presented how to create a mailer and how to test it. In reality, you may find that writing your tests before you actually write your code to be a rewarding experience. It may take some time to get used to TDD (Test Driven Development), but coding this way achieves two major benefits. Firstly, you know that the code does indeed work, because the tests fail (because there's no code), then they pass, because the code that satisfies the tests was written. Secondly, when you start with the tests, you don't have to make time AFTER you write the code, to write the tests, then never get around to it. The tests are already there and testing has now become part of your coding regimen.
+
+== Changelog ==
+
+http://rails.lighthouseapp.com/projects/16213/tickets/25[Lighthouse ticket] \ No newline at end of file
diff --git a/railties/doc/guides/source/actioncontroller_basics/http_auth.txt b/railties/doc/guides/source/actioncontroller_basics/http_auth.txt
index 8deb40c2c9..63e7c0f061 100644
--- a/railties/doc/guides/source/actioncontroller_basics/http_auth.txt
+++ b/railties/doc/guides/source/actioncontroller_basics/http_auth.txt
@@ -1,6 +1,13 @@
-== HTTP Basic Authentication ==
+== HTTP Authentications ==
-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, `authenticate_or_request_with_http_basic`.
+Rails comes with two built-in HTTP authentication mechanisms :
+
+ * Basic Authentication
+ * Digest Authentication
+
+=== HTTP Basic Authentication ===
+
+HTTP Basic authentication 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, `authenticate_or_request_with_http_basic`.
[source, ruby]
-------------------------------------
@@ -10,7 +17,7 @@ class AdminController < ApplicationController
before_filter :authenticate
-private
+ private
def authenticate
authenticate_or_request_with_http_basic do |username, password|
@@ -22,3 +29,29 @@ end
-------------------------------------
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.
+
+=== HTTP Digest Authentication ===
+
+HTTP Digest authentication is superior to the Basic authentication as it does not require the client to send unencrypted password over the network. Using Digest authentication with Rails is quite easy and only requires using one method, +authenticate_or_request_with_http_digest+.
+
+[source, ruby]
+-------------------------------------
+class AdminController < ApplicationController
+
+ USERS = { "lifo" => "world" }
+
+ before_filter :authenticate
+
+ private
+
+ def authenticate
+ authenticate_or_request_with_http_digest do |username|
+ USERS[username]
+ end
+ end
+
+end
+-------------------------------------
+
+
+As seen in the example above, +authenticate_or_request_with_http_digest+ block takes only one argument - the username. And the block returns the password. Returning +false+ or +nil+ from the +authenticate_or_request_with_http_digest+ will cause authentication failure.
diff --git a/railties/doc/guides/source/active_record_basics.txt b/railties/doc/guides/source/active_record_basics.txt
index 367a1bba5e..dd62b9a948 100644
--- a/railties/doc/guides/source/active_record_basics.txt
+++ b/railties/doc/guides/source/active_record_basics.txt
@@ -1,134 +1,118 @@
Active Record Basics
====================
-Active Record is a design pattern that mitigates the mind-numbing mental gymnastics often needed to get your application to communicate with a database. This guide uses a mix of real-world examples, metaphors and detailed explanations of the actual Rails source code to help you make the most of ActiveRecord.
+This guide will give you a strong grasp of the Active Record pattern and how it can be used with or without Rails. Hopefully, some of the philosophical and theoretical intentions discussed here will also make you a stronger and better developer.
-After reading this guide readers should have a strong grasp of the Active Record pattern and how it can be used with or without Rails. Hopefully, some of the philosophical and theoretical intentions discussed here will also make them a stronger and better developer.
+After reading this guide we hope that you'll be able to:
-== ORM The Blueprint of Active Record
+* Understand the way Active Record fits into the MVC model.
+* Create basic Active Record models and map them with your database tables.
+* Use your models to execute CRUD (Create, Read, Update and Delete) database operations.
+* Follow the naming conventions used by Rails to make developing database applications easier and obvious.
+* Take advantage of the way Active Record maps it's attributes with the database tables' columns to implement your application's logic.
+* Use Active Record with legacy databases that do not follow the Rails naming conventions.
-If Active Record is the engine of Rails then ORM is the blueprint of that engine. ORM is short for “Object Relational Mapping” and is a programming concept used to make structures within a system relational. As a thought experiment imagine the components that make up a typical car. There are doors, seats, windows, engines etc. Viewed independently they are simple parts, yet when bolted together through the aid of a blueprint, the parts become a more complex device. ORM is the blueprint that describes how the individual parts relate to one another and in some cases infers the part’s purpose through the way the associations are described.
+== What's Active Record
-== Active Record The Engine of Rails
+Rails' ActiveRecord is an implementation of Martin Fowler's http://martinfowler.com/eaaCatalog/activeRecord.html[Active Record Design Pattern]. This pattern is based on the idea of creating relations between the database and the application in the following way:
-Active Record is a design pattern used to access data within a database. The name “Active Record” was coined by Martin Fowler in his book “Patterns of Enterprise Application Architecture”. Essentially, when a record is returned from the database instead of being just the data it is wrapped in a class, which gives you methods to control that data with. The rails framework is built around the MVC (Model View Controller) design patten and the Active Record is used as the default Model.
+* Each database table is mapped to a class.
+* Each table column is mapped to an attribute of this class.
+* Each instance of this class is mapped to a single row in the database table.
-The Rails community added several useful concepts to their version of Active Record, including inheritance and associations, which are extremely useful for web applications. The associations are created by using a DSL (domain specific language) of macros, and inheritance is achieved through the use of STI (Single Table Inheritance) at the database level.
+The definition of the Active Record pattern in Martin Fowler's words:
-By following a few simple conventions the Rails Active Record will automatically map between:
+"_An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data."_
-* Classes & Database Tables
-* Class attributes & Database Table Columns
+== Object Relational Mapping
-=== Rails Active Record Conventions
-Here are the key conventions to consider when using Active Record.
+The relation between databases and object-oriented software is called ORM, which is short for "Object Relational Mapping". The purpose of an ORM framework is to minimize the mismatch existent between relational databases and object-oriented software. In applications with a domain model, we have objects that represent both the state of the system and the behaviour of the real world elements that were modeled through these objects. Since we need to store the system's state somehow, we can use relational databases, which are proven to be an excelent approach to data management. Usually this may become a very hard thing to do, since we need to create an object-oriented model of everything that lives in the database, from simple columns to complicated relations between different tables. Doing this kind of thing by hand is a tedious and error prone job. This is where an ORM framework comes in.
-==== Naming Conventions
-Database Table - Plural with underscores separating words i.e. (book_clubs)
-Model Class - Singular with the first letter of each word capitalized i.e. (BookClub)
-Here are some additional Examples:
-
-[grid="all"]
-`-------------`---------------
-Model / Class Table / Schema
-----------------------------
-Post posts
-LineItem line_items
-Deer deer
-Mouse mice
-Person people
-----------------------------
-
-==== Schema Conventions
-
-To take advantage of some of the magic of Rails database tables must be modeled
-to reflect the ORM decisions that Rails makes.
-
-[grid="all"]
-`-------------`---------------------------------------------------------------------------------
-Convention
--------------------------------------------------------------------------------------------------
-Foreign keys These fields are named table_id i.e. (item_id, order_id)
-Primary Key Rails automatically creates a primary key column named "id" unless told otherwise.
--------------------------------------------------------------------------------------------------
-
-==== Magic Field Names
-
-When these optional fields are used in your database table definition they give the Active Record
-instance additional features.
-
-NOTE: While these column names are optional they are in fact reserved by ActiveRecord. Steer clear of reserved keywords unless you want the extra functionality. For example, "type" is a reserved keyword
-used to designate a table using Single Table Inheritance. If you are not using STI, try an analogous
-keyword like "context", that may still accurately describe the data you are modeling.
-
-[grid="all"]
-`------------------------`------------------------------------------------------------------------------
-Attribute Purpose
-------------------------------------------------------------------------------------------------------
-created_at / created_on Rails stores the current date & time to this field when creating the record.
-updated_at / updated_on Rails stores the current date & time to this field when updating the record.
-lock_version Adds optimistic locking to a model link:http://api.rubyonrails.com/classes/ActiveRecord/Locking.html[more about optimistic locking].
-type Specifies that the model uses Single Table Inheritance link:http://api.rubyonrails.com/classes/ActiveRecord/Base.html[more about STI].
-id All models require an id. the default is name is "id" but can be changed using the "set_primary_key" or "primary_key" methods.
-_table_name_\_count Can be used to caches the number of belonging objects on the associated class.
-------------------------------------------------------------------------------------------------------
-
-By default rails assumes all tables will use “id” as their primary key to identify each record. Though fortunately you won’t have explicitly declare this, Rails will automatically create that field unless you tell it not to.
-
-For example suppose you created a database table called cars:
+== ActiveRecord as an ORM framework
-[source, sql]
--------------------------------------------------------
-mysql> CREATE TABLE cars (
- id INT,
- color VARCHAR(100),
- doors INT,
- horses INT,
- model VARCHAR(100)
- );
--------------------------------------------------------
-
-Now you created a class named Car, which is to represent an instance of a record from your table.
+ActiveRecord gives us several mechanisms, being the most important ones the hability to:
-[source, ruby]
--------------------------------------------------------
-class Car
-end
--------------------------------------------------------
+* Represent models.
+* Represent associations between these models.
+* Represent inheritance hierarquies through related models.
+* Validate models before they get recorded to the database.
+* Perform database operations in an object-oriented fashion.
-As you might expect without defining the explicit mappings between your class and the table it is impossible for Rails or any other program to correctly map those relationships.
+It's easy to see that the Rails Active Record implementation goes way beyond the basic description of the Active Record Pattern.
-[source, ruby]
--------------------------------------------------------
->> c = Car.new
-=> #<Class:0x11e1e90>
->> c.doors
-NoMethodError: undefined method `doors' for #<Class:0x11e1e90>
- from (irb):2
--------------------------------------------------------
-
-Now you could define a door methods to write and read data to and from the database. In a nutshell this is what ActiveRecord does. According to the Rails API:
-“Active Record objects don‘t specify their attributes directly, but rather infer them from the table definition with which they‘re linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.”
-Lets try our Car class again, this time inheriting from ActiveRecord.
+== Active Record inside the MVC model
+
+Active Record plays the role of model inside the MVC structure followed by Rails applications. Since model objects should encapsulate both state and logic of your applications, it's ActiveRecord responsability to deliver you the easiest possible way to recover this data from the database.
+
+== Creating ActiveRecord models
+
+It's very easy to create ActiveRecord models. All you have to do is to subclass the ActiveRecord::Base class and you're good to go:
[source, ruby]
--------------------------------------------------------
-class Car < ActiveRecord::Base
-end
--------------------------------------------------------
+------------------------------------------------------------------
+class Product < ActiveRecord::Base; end
+------------------------------------------------------------------
+
+This will create a +Product+ model, mapped to a *products* table at the database. By doing this you'll also have the hability to map the columns of each row in that table with the attributes of the instances of your model. So, suppose that the *products* table was created using a SQL sentence like:
+
+[source, sql]
+------------------------------------------------------------------
+CREATE TABLE products (
+ id int(11) NOT NULL auto_increment,
+ name varchar(255),
+ PRIMARY KEY (id)
+);
+------------------------------------------------------------------
-Now if we try to access an attribute of the table ActiveRecord automatically handles the mappings for us, as you can see in the following example.
+Following the table schema above, you would be able to write code like the following:
[source, ruby]
--------------------------------------------------------
->> c = Car.new
-=> #<Car id: nil, doors: nil, color: nil, horses: nil, model: nil>
->> c.doors
-=> nil
--------------------------------------------------------
+------------------------------------------------------------------
+p = Product.new
+p.name = "Some Book"
+puts p.name # "Some Book"
+------------------------------------------------------------------
+
+== Convention over Configuration in ActiveRecord
+
+When writing applications using other programming languages or frameworks, it may be necessary to write a lot of configuration code. This is particulary true for ORM frameworks in general. However, if you follow the conventions adopted by Rails, you'll need to write very little configuration (in some case no configuration at all) when creating ActiveRecord models. The idea is that if you configure your applications in the very same way most of the times then this should be the default way. In this cases, explicity configuration would be needed only in those cases where you can't follow the conventions for any reason.
+
+=== Naming Conventions
+
+By default, ActiveRecord uses some naming conventions to find out how the mapping between models and database tables should be created. Rails will pluralize your class names to find the respective database table. So, for a class +Book+, you should have a database table called *books*. The Rails pluralization mechanisms are very powerful, being capable to pluralize (and singularize) both regular and irregular words. When using class names composed of two or more words, the model class name should follow the Ruby conventions, using the camelCase form, while the table name must contain the words separated by underscores. Examples:
+
+Database Table - Plural with underscores separating words i.e. (book_clubs)
+Model Class - Singular with the first letter of each word capitalized i.e. (BookClub)
+
+[width="60%", options="header"]
+|==============================
+|Model / Class |Table / Schema
+|Post |posts
+|LineItem |line_items
+|Deer |deer
+|Mouse |mice
+|Person |people
+|==============================
+
+=== Schema Conventions
+
+ActiveRecord uses naming conventions for the columns in database tables, depending on the purpose of these columns.
+
+* *Foreign keys* - These fields should be named following the pattern table_id i.e. (item_id, order_id). These are the fields that ActiveRecord will look for when you create associations between your models.
+* *Primary keys* - By default, ActiveRecord will use a integer column named "id" as the table's primary key. When using http://guides.rails.info/migrations.html[Rails Migrations] to create your tables, this column will be automaticaly created.
+
+There are also some optional column names that will create additional features to ActiveRecord instances:
+
+* *created_at / created_on* - ActiveRecord will store the current date and time to this field when creating the record.
+* *updated_at / updated_on* - ActiveRecord will store the current date and times to this field when updating the record.
+* *lock_version* - Adds http://api.rubyonrails.com/classes/ActiveRecord/Locking.html[optimistic locking] to a model.
+* *type* - Specifies that the model uses http://api.rubyonrails.com/classes/ActiveRecord/Base.html[Single Table Inheritance]
+* *(table_name)_count* - Used to cache the number of belonging objects on associations. For example, a +comments_count+ column in a +Post+ class that has many instances of +Comment+ will cache the number of existent comments for each post.
+
+NOTE: While these column names are optional they are in fact reserved by ActiveRecord. Steer clear of reserved keywords unless you want the extra functionality. For example, "type" is a reserved keyword used to designate a table using Single Table Inheritance. If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling.
+
+ == STOPED HERE
-Rails further extends this model by giving each ActiveRecord a way of describing the variety of ways records are associated with one another. We will touch on some of these associations later in the guide but I encourage readers who are interested to read the guide to ActiveRecord associations for an in-depth explanation of the variety of ways rails can model associations.
-- Associations between objects controlled by meta-programming macros.
== Philosophical Approaches & Common Conventions
Rails has a reputation of being a zero-config framework which means that it aims to get you off the ground with as little pre-flight checking as possible. This speed benefit is achieved by following “Convention over Configuration”, which is to say that if you agree to live with the defaults then you benefit from a the inherent speed-boost. As Courtneay Gasking put it to me once “You don’t want to off-road on Rails”. ActiveRecord is no different, while it’s possible to override or subvert any of the conventions of AR, unless you have a good reason for doing so you will probably be happy with the defaults. The following is a list of the common conventions of ActiveRecord
@@ -151,4 +135,4 @@ Rails has a reputation of being a zero-config framework which means that it aim
== ActiveRecord handling the CRUD of your Rails application - Understanding the life-cycle of an ActiveRecord
== Validations & Callbacks
-see the Validations & Callbacks guide for more info. \ No newline at end of file
+see the Validations & Callbacks guide for more info.
diff --git a/railties/doc/guides/source/creating_plugins/creating_plugins/lib/main.rb b/railties/doc/guides/source/creating_plugins/creating_plugins/lib/main.rb
new file mode 100644
index 0000000000..b0919153f1
--- /dev/null
+++ b/railties/doc/guides/source/creating_plugins/creating_plugins/lib/main.rb
@@ -0,0 +1,4 @@
+# To change this template, choose Tools | Templates
+# and open the template in the editor.
+
+puts "Hello World"
diff --git a/railties/doc/guides/source/creating_plugins/generator_commands.txt b/railties/doc/guides/source/creating_plugins/generator_commands.txt
index f60ea3d8f1..6ded0dde59 100644
--- a/railties/doc/guides/source/creating_plugins/generator_commands.txt
+++ b/railties/doc/guides/source/creating_plugins/generator_commands.txt
@@ -120,7 +120,7 @@ Rails::Generator::Commands::List.send :include, Yaffle::Generator::Commands
Rails::Generator::Commands::Update.send :include, Yaffle::Generator::Commands::Update
-----------------------------------------------------------
-*vendor/plugins/yaffle/generators/yaffle/yaffle_route_generator.rb*
+*vendor/plugins/yaffle/generators/yaffle_route/yaffle_route_generator.rb*
[source, ruby]
-----------------------------------------------------------
diff --git a/railties/doc/guides/source/creating_plugins/migrations.txt b/railties/doc/guides/source/creating_plugins/migrations.txt
index e7d2e09069..2589169b38 100644
--- a/railties/doc/guides/source/creating_plugins/migrations.txt
+++ b/railties/doc/guides/source/creating_plugins/migrations.txt
@@ -28,26 +28,7 @@ Here are a few possibilities for how to allow developers to use your plugin migr
=== Create a custom rake task ===
-*vendor/plugins/yaffle/lib/db/migrate/20081116181115_create_birdhouses.rb:*
-
-[source, ruby]
-----------------------------------------------
-class CreateBirdhouses < ActiveRecord::Migration
- def self.up
- create_table :birdhouses, :force => true do |t|
- t.string :name
- t.timestamps
- end
- end
-
- def self.down
- drop_table :birdhouses
- end
-end
-----------------------------------------------
-
-
-*vendor/plugins/yaffle/tasks/yaffle.rake:*
+*vendor/plugins/yaffle/tasks/yaffle_tasks.rake:*
[source, ruby]
----------------------------------------------
@@ -153,7 +134,7 @@ NOTE: the migration generator checks to see if a migation already exists, and it
After running the test with 'rake' you can make it pass with:
-*vendor/plugins/yaffle/generators/yaffle/yaffle_generator.rb*
+*vendor/plugins/yaffle/generators/yaffle_migration/yaffle_migration_generator.rb*
[source, ruby]
------------------------------------------------------------------
diff --git a/railties/doc/guides/source/creating_plugins/models.txt b/railties/doc/guides/source/creating_plugins/models.txt
index 505ab44a71..1498b8e26c 100644
--- a/railties/doc/guides/source/creating_plugins/models.txt
+++ b/railties/doc/guides/source/creating_plugins/models.txt
@@ -20,7 +20,7 @@ vendor/plugins/yaffle/
As always, start with a test:
-*vendor/plugins/yaffle/yaffle/woodpecker_test.rb:*
+*vendor/plugins/yaffle/test/woodpecker_test.rb:*
[source, ruby]
----------------------------------------------
diff --git a/railties/doc/guides/source/creating_plugins/tasks.txt b/railties/doc/guides/source/creating_plugins/tasks.txt
index d848c2cfa1..edaffec194 100644
--- a/railties/doc/guides/source/creating_plugins/tasks.txt
+++ b/railties/doc/guides/source/creating_plugins/tasks.txt
@@ -1,10 +1,10 @@
== Rake tasks ==
-When you created the plugin with the built-in rails generator, it generated a rake file for you in 'vendor/plugins/yaffle/tasks/yaffle.rake'. Any rake task you add here will be available to the app.
+When you created the plugin with the built-in rails generator, it generated a rake file for you in 'vendor/plugins/yaffle/tasks/yaffle_tasks.rake'. Any rake task you add here will be available to the app.
Many plugin authors put all of their rake tasks into a common namespace that is the same as the plugin, like so:
-*vendor/plugins/yaffle/tasks/yaffle.rake*
+*vendor/plugins/yaffle/tasks/yaffle_tasks.rake*
[source, ruby]
---------------------------------------------------------
diff --git a/railties/doc/guides/source/creating_plugins/test_setup.txt b/railties/doc/guides/source/creating_plugins/test_setup.txt
index 64236ff110..9ee98c9935 100644
--- a/railties/doc/guides/source/creating_plugins/test_setup.txt
+++ b/railties/doc/guides/source/creating_plugins/test_setup.txt
@@ -116,9 +116,6 @@ ActiveRecord::Schema.define(:version => 0) do
t.string :last_tweet
t.datetime :last_tweeted_at
end
- create_table :woodpeckers, :force => true do |t|
- t.string :name
- end
end
----------------------------------------------
diff --git a/railties/doc/guides/source/form_helpers.txt b/railties/doc/guides/source/form_helpers.txt
index f4039070dd..e2afcf41ba 100644
--- a/railties/doc/guides/source/form_helpers.txt
+++ b/railties/doc/guides/source/form_helpers.txt
@@ -1,15 +1,16 @@
Rails form helpers
==================
-Mislav Marohnić <mislav.marohnic@gmail.com>
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.
In this guide you will:
-* Create search forms and similar kind of generic forms not representing any specific model in your application;
-* Make model-centric forms for creation and editing of specific database records;
-* Generate select boxes from multiple types of data;
-* Learn what makes a file upload form different;
+* Create search forms and similar kind of generic forms not representing any specific model in your application
+* Make model-centric forms for creation and editing of specific database records
+* Generate select boxes from multiple types of data
+* Understand the date and time helpers Rails provides
+* Learn what makes a file upload form different
+* Find out where to look for complex forms
NOTE: This guide is not intended to be a complete documentation of available form helpers and their arguments. Please visit http://api.rubyonrails.org/[the Rails API documentation] for a complete reference.
@@ -25,7 +26,7 @@ The most basic form helper is `form_tag`.
<% end %>
----------------------------------------------------------------------------
-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):
+When called without arguments like this, it creates a form element that has the current page as its action and "post" as its method (some line breaks added for readability):
.Sample output from `form_tag`
----------------------------------------------------------------------------
@@ -37,12 +38,12 @@ When called without arguments like this, it creates a form element that has the
</form>
----------------------------------------------------------------------------
-If you carefully observe this output, you can see that the helper generated something you didn't specify: a `div` element with a hidden input inside. This is a security feature of Rails called *cross-site request forgery protection* and form helpers generate it for every form which action isn't "GET" (provided that this security feature is enabled).
+If you carefully observe this output, you can see that the helper generated something you didn't specify: a `div` element with a hidden input inside. This is a security feature of Rails called *cross-site request forgery protection* and form helpers generate it for every form whose action is not "get" (provided that this security feature is enabled). You can read more about this in the link:./security.html#_cross_site_reference_forgery_csrf[Ruby On Rails Security Guide].
NOTE: Throughout this guide, this `div` with the hidden input will be stripped away to have clearer code samples.
-Generic search form
-~~~~~~~~~~~~~~~~~~~
+A Generic search form
+~~~~~~~~~~~~~~~~~~~~~
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:
@@ -51,9 +52,9 @@ Probably the most minimal form often seen on the web is a search form with a sin
3. a text input element, and
4. a submit element.
-IMPORTANT: 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 others.
+IMPORTANT: Always use "GET" as the method for search forms. This allows users are able to bookmark a specific search and get back to it, more generally Rails encourages you to use the right HTTP verb for an action.
-To create that, you will use `form_tag`, `label_tag`, `text_field_tag` and `submit_tag`, respectively.
+To create this form you will use `form_tag`, `label_tag`, `text_field_tag` and `submit_tag`, respectively.
.A basic search form
----------------------------------------------------------------------------
@@ -88,10 +89,10 @@ Besides `text_field_tag` and `submit_tag`, there is a similar helper for _every_
TIP: For every form input, an ID attribute is generated from its name ("q" in the example). These IDs can be very useful for CSS styling or manipulation of form controls with JavaScript.
-Multiple hashes in form helper attributes
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Multiple hashes in form helper calls
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-By now you've seen that the `form_tag` helper accepts 2 arguments: the path for the action and an options hash. This hash specifies the method of form submission and HTML options such as the form element's class.
+By now you've seen that the `form_tag` helper accepts 2 arguments: the path for the action and an options hash. This hash specifies the method of form submission and HTML options such as the form element's class.
As with the `link_to` helper, the path argument doesn't have to be given a string. It can be a hash of URL parameters that Rails' routing mechanism will turn into a valid URL. Still, you cannot simply write this:
@@ -116,7 +117,7 @@ WARNING: Do not delimit the second hash without doing so with the first hash, ot
Helpers for generating form elements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Rails provides a series of helpers for generating form elements such as checkboxes, text fields, radio buttons and so. These basic helpers, with names ending in _tag such as `text_field_tag`, `check_box_tag` just generate a single `<input>` element. The first parameter to these is always the name of the input. This is the name under which value will appear in the `params` hash in the controller. For example if the form contains
+Rails provides a series of helpers for generating form elements such as checkboxes, text fields, radio buttons and so. These basic helpers, with names ending in _tag such as `text_field_tag`, `check_box_tag` just generate a single `<input>` element. The first parameter to these is always the name of the input. In the controller, this name will be the key in the `params` hash used to get the value entered by the user. For example if the form contains
---------------------------
<%= text_field_tag(:query) %>
@@ -126,7 +127,7 @@ then the controller code should use
---------------------------
params[:query]
---------------------------
-to retrieve the value entered by the user. When naming inputs be aware that Rails uses certain conventions that control whether values appear at the top level of the params hash, inside an array or a nested hash and so on. You can read more about them in the <<parameter_names,parameter names>> section. For details on the precise usage of these helpers, please refer to the http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html[API documentation].
+to retrieve the value entered by the user. When naming inputs be aware that Rails uses certain conventions that control whether values are at the top level of the `params` hash, inside an array or a nested hash and so on. You can read more about them in the <<parameter_names,parameter names>> section. For details on the precise usage of these helpers, please refer to the http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html[API documentation].
Checkboxes
^^^^^^^^^^
@@ -146,7 +147,7 @@ output:
<label for="pet_cat">I own a cat</label>
----------------------------------------------------------------------------
-The second parameter to `check_box_tag` is the value of the input. This is the value that will be submitted by the browser if the checkbox is ticked (i.e. the value that will be present in the params hash). With the above form you would check the value of `params[:pet_dog]` and `params[:pet_cat]` to see which pets the user owns.
+The second parameter to `check_box_tag` is the value of the input. This is the value that will be submitted by the browser if the checkbox is ticked (i.e. the value that will be present in the `params` hash). With the above form you would check the value of `params[:pet_dog]` and `params[:pet_cat]` to see which pets the user owns.
Radio buttons
^^^^^^^^^^^^^
@@ -166,7 +167,7 @@ output:
<label for="age_adult">I'm over 21</label>
----------------------------------------------------------------------------
-As with `check_box_tag` the second parameter to `radio_button_tag` is the value of the input. Because these two radio buttons share the same name (age) the user will only be able to select one and `params[:age]` will contain either `child` or `adult`.
+As with `check_box_tag` the second parameter to `radio_button_tag` is the value of the input. Because these two radio buttons share the same name (age) the user will only be able to select one and `params[:age]` will contain either "child" or "adult".
IMPORTANT: Always use labels for each checkbox and radio button. They associate text with a specific option and provide a larger clickable region.
@@ -197,7 +198,7 @@ Dealing With Model Objects
Model object helpers
~~~~~~~~~~~~~~~~~~~~~~
-A particularly common task for a form is editing or creating a model object. While the `*_tag` helpers could certainly be used for this task they are somewhat verbose as for each tag you would have to ensure the correct parameter name is used and set the default value of the input appropriately. Rails provides helpers tailored to this task. These helpers lack the _tag suffix, for example `text_field`, `text_area`.
+A particularly common task for a form is editing or creating a model object. While the `*_tag` helpers can certainly be used for this task they are somewhat verbose as for each tag you would have to ensure the correct parameter name is used and set the default value of the input appropriately. Rails provides helpers tailored to this task. These helpers lack the _tag suffix, for example `text_field`, `text_area`.
For these helpers the first argument is the name of an instance variable and the second is the name of a method (usually an attribute) to call on that object. Rails will set the value of the input control to the return value of that method for the object and set an appropriate input name. If your controller has defined `@person` and that person's name is Henry then a form containing:
@@ -208,7 +209,7 @@ will produce output similar to
---------------------------
<input id="person_name" name="person[name]" type="text" value="Henry"/>
---------------------------
-Upon form submission the value entered by the user will be stored in `params[:person][:name]`. The `params[:person]` hash is suitable for passing to `Person.new` or, if `@person` is an instance of Person, `@person.update_attributes`.
+Upon form submission the value entered by the user will be stored in `params[:person][:name]`. The `params[:person]` hash is suitable for passing to `Person.new` or, if `@person` is an instance of Person, `@person.update_attributes`. While the name of an attribute is the most common second parameter to these helpers this is not compulsory. In the example above, as long as person objects have a `name` and a `name=` method Rails will be happy.
[WARNING]
============================================================================
@@ -258,13 +259,13 @@ The resulting HTML is:
<input name="commit" type="submit" value="Create" />
</form>
----------------------------------------------------------------------------
-The name passed to `form_for` controls where in the params hash the form values will appear. Here the name is `article` and so all the inputs have names of the form `article[attribute_name]`. Accordingly, in the `create` action `params[:article]` will be a hash with keys `:title` and `:body`. You can read more about the significance of input names in the <<parameter_names,parameter names>> section.
+The name passed to `form_for` controls the key used in `params` to access the form's values. Here the name is `article` and so all the inputs have names of the form `article[attribute_name]`. Accordingly, in the `create` action `params[:article]` will be a hash with keys `:title` and `:body`. You can read more about the significance of input names in the <<parameter_names,parameter names>> section.
The helper methods called on the form builder are identical to the model object helpers except that it is not necessary to specify which object is being edited since this is already managed by the form builder.
-You can create a similar binding without actually creating `<form>` tags with the `fields_for` helper. This is useful for editing additional model objects with the same form. For example if you had a Person model with an associated ContactDetail model you could create a form for editing both like so:
+You can create a similar binding without actually creating `<form>` tags with the `fields_for` helper. This is useful for editing additional model objects with the same form. For example if you had a Person model with an associated ContactDetail model you could create a form for creating both like so:
-------------
-<% form_for @person do |person_form| %>
+<% form_for :person, @person, :url => { :action => "create" } do |person_form| %>
<%= person_form.text_field :name %>
<% fields_for @person.contact_detail do |contact_details_form| %>
<%= contact_details_form.text_field :phone_number %>
@@ -275,7 +276,7 @@ You can create a similar binding without actually creating `<form>` tags with t
which produces the following output:
-------------
-<form action="/people/1" class="edit_person" id="edit_person_1" method="post">
+<form action="/people/create" class="new_person" id="new_person" method="post">
<input id="person_name" name="person[name]" size="30" type="text" />
<input id="contact_detail_phone_number" name="contact_detail[phone_number]" size="30" type="text" />
</form>
@@ -285,7 +286,7 @@ The object yielded by `fields_for` is a form builder like the one yielded by `fo
Relying on record identification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The Article model is directly available to users of our application, so -- following the best practices for developing with Rails -- you should declare it *a resource*.
+The Article model is directly available to users of the application, so -- following the best practices for developing with Rails -- you should declare it *a resource*.
When dealing with RESTful resources, calls to `form_for` can get significantly easier if you rely on *record identification*. In short, you can just pass the model instance and have Rails figure out model name and the rest:
@@ -305,7 +306,7 @@ form_for(@article)
Notice how the short-style `form_for` 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 `record.new_record?`. It also selects the correct path to submit to and the name based on the class of the object.
-Rails will also automatically set the class and id of the form appropriately: a form creating an article would have id and class `new_article`. If you were editing the article with id 23 the class would be set to `edit_article` and the id to `edit_article_23`. The attributes will be omitted or brevity in the rest of this guide.
+Rails will also automatically set the `class` and `id` of the form appropriately: a form creating an article would have `id` and `class` `new_article`. If you were editing the article with id 23 the `class` would be set to `edit_article` and the id to `edit_article_23`. These attributes will be omitted for brevity in the rest of this guide.
WARNING: 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, `:url` and `:method` explicitly.
@@ -327,7 +328,7 @@ For more information on Rails' routing system and the associated conventions, pl
How do forms with PUT or DELETE methods work?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-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 _don't support_ methods other than "GET" and "POST" when it comes to submitting forms. How does this work, then?
+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 _don't support_ methods other than "GET" and "POST" when it comes to submitting forms.
Rails works around this issue by emulating other methods over POST with a hidden input named `"_method"` that is set to reflect the desired method:
@@ -343,7 +344,7 @@ output:
</div>
...
----------------------------------------------------------------------------
-When parsing POSTed data, Rails will take into account the special `_method` parameter and act as if the HTTP method was the one specified inside it ("PUT" in this example).
+When parsing POSTed data, Rails will take into account the special `_method` parameter and acts as if the HTTP method was the one specified inside it ("PUT" in this example).
Making select boxes with ease
@@ -355,7 +356,7 @@ Here is what the markup might look like:
----------------------------------------------------------------------------
<select name="city_id" id="city_id">
- <option value="1">Lisabon</option>
+ <option value="1">Lisbon</option>
<option value="2">Madrid</option>
...
<option value="12">Berlin</option>
@@ -364,28 +365,28 @@ Here is what the markup might look like:
Here you have a list of cities whose names are presented to the user. Internally the application only wants to handle their IDs so they are used as the options' value attribute. Let's see how Rails can help out here.
-The select tag and options
+The select and options tag
~~~~~~~~~~~~~~~~~~~~~~~~~~
The most generic helper is `select_tag`, which -- as the name implies -- simply generates the `SELECT` tag that encapsulates an options string:
----------------------------------------------------------------------------
-<%= select_tag(:city_id, '<option value="1">Lisabon</option>...') %>
+<%= select_tag(:city_id, '<option value="1">Lisbon</option>...') %>
----------------------------------------------------------------------------
-This is a start, but it doesn't dynamically create our option tags. You can generate option tags with the `options_for_select` helper:
+This is a start, but it doesn't dynamically create the option tags. You can generate option tags with the `options_for_select` helper:
----------------------------------------------------------------------------
-<%= options_for_select([['Lisabon', 1], ['Madrid', 2], ...]) %>
+<%= options_for_select([['Lisbon', 1], ['Madrid', 2], ...]) %>
output:
-<option value="1">Lisabon</option>
+<option value="1">Lisbon</option>
<option value="2">Madrid</option>
...
----------------------------------------------------------------------------
-For input data you use a nested array where each element has two elements: option text (city name) and option value (city id). The option value is what will get submitted to your controller. It is often true that the option value is the id of a corresponding database object but this does not have to be the case.
+The first argument to `options_for_select` is a nested array where each element has two elements: option text (city name) and option value (city id). The option value is what will be submitted to your controller. Often this will be the id of a corresponding database object but this does not have to be the case.
Knowing this, you can combine `select_tag` and `options_for_select` to achieve the desired, complete markup:
@@ -393,71 +394,68 @@ Knowing this, you can combine `select_tag` and `options_for_select` to achieve t
<%= select_tag(:city_id, options_for_select(...)) %>
----------------------------------------------------------------------------
-Sometimes, depending on an application's needs, you also wish a specific option to be pre-selected. The `options_for_select` helper supports this with an optional second argument:
+`options_for_select` allows you to pre-select an option by passing its value.
----------------------------------------------------------------------------
-<%= options_for_select([['Lisabon', 1], ['Madrid', 2], ...], 2) %>
+<%= options_for_select([['Lisbon', 1], ['Madrid', 2], ...], 2) %>
output:
-<option value="1">Lisabon</option>
+<option value="1">Lisbon</option>
<option value="2" selected="selected">Madrid</option>
...
----------------------------------------------------------------------------
-So whenever Rails sees that the internal value of an option being generated matches this value, it will add the `selected` attribute to that option.
+Whenever Rails sees that the internal value of an option being generated matches this value, it will add the `selected` attribute to that option.
[TIP]
============================================================================
-The second argument to `options_for_select` must be exactly equal to the desired internal value. In particular if the internal value is the integer 2 you cannot pass "2" to `options_for_select` -- you must pass 2. Be aware of values extracted from the params hash as they are all strings.
+The second argument to `options_for_select` must be exactly equal to the desired internal value. In particular if the value is the integer 2 you cannot pass "2" to `options_for_select` -- you must pass 2. Be aware of values extracted from the `params` hash as they are all strings.
============================================================================
Select boxes for dealing with models
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Until now you've seen 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 you have a "Person" model with a `city_id` attribute.
-
-Consistent with other form helpers, when dealing with models you drop the `_tag` suffix from `select_tag`.
+In most cases form controls will be tied to a specific database model and as you might expect Rails provides helpers tailored for that purpose. Consistent with other form helpers, when dealing with models you drop the `_tag` suffix from `select_tag`:
----------------------------------------------------------------------------
# controller:
@person = Person.new(:city_id => 2)
# view:
-<%= select(:person, :city_id, [['Lisabon', 1], ['Madrid', 2], ...]) %>
+<%= select(:person, :city_id, [['Lisbon', 1], ['Madrid', 2], ...]) %>
----------------------------------------------------------------------------
Notice that the third parameter, the options array, is the same kind of argument you pass to `options_for_select`. One advantage here is that you don't have to worry about pre-selecting the correct city if the user already has one -- Rails will do this for you by reading from the `@person.city_id` attribute.
-As before, if you were to use `select` helper on a form builder scoped to `@person` object, the syntax would be:
+As with other helpers, if you were to use `select` helper on a form builder scoped to `@person` object, the syntax would be:
----------------------------------------------------------------------------
# select on a form builder
<%= f.select(:city_id, ...) %>
----------------------------------------------------------------------------
-[WARNING]
+[WARNING]
=============================
-If you are using `select` (or similar helpers such as `collection_select`, `select_tag`) to set a `belongs_to` association you must pass the name of the foreign key (in the example above `city_id`), not the name of association itself. If you specify `city` instead of `city_id Active Record will raise an error along the lines of
+If you are using `select` (or similar helpers such as `collection_select`, `select_tag`) to set a `belongs_to` association you must pass the name of the foreign key (in the example above `city_id`), not the name of association itself.
+
+If you specify `city` instead of `city_id` Active Record will raise an error along the lines of
--------
-ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got Fixnum(#1138750)
+ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750)
--------
-when you pass the params hash to `Person.new` or `update_attributes`. Another way of looking at this is that form helpers only edit attributes.
+when you pass the `params` hash to `Person.new` or `update_attributes`. Another way of looking at this is that form helpers only edit attributes.
+
+You should also be aware of the potential security ramifications of allowing users to edit foreign keys directly. You may wish to consider the use of `attr_protected` and `attr_accessible`. For further details on this, see the link:security.html#_mass_assignment[Ruby On Rails Security Guide].
============================
+
Option tags from a collection of arbitrary objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Until now you were generating option tags from nested arrays with the help of `options_for_select` method. Data in our array were raw values:
+Generating options tags with `options_for_select` requires that you create an array containing the text and value for each option. But what if you had a City model (perhaps an Active Record one) and you wanted to generate option tags from a collection of those objects? One solution would be to make a nested array by iterating over them:
----------------------------------------------------------------------------
-<%= options_for_select([['Lisabon', 1], ['Madrid', 2], ...]) %>
-----------------------------------------------------------------------------
-
-But what if you had a *City* model (perhaps an Active Record one) and you wanted to generate option tags from a collection of those objects? One solution would be to make a nested array by iterating over them:
-
-----------------------------------------------------------------------------
-<% cities_array = City.find(:all).map { |city| [city.name, city.id] } %>
+<% cities_array = City.all.map { |city| [city.name, city.id] } %>
<%= options_for_select(cities_array) %>
----------------------------------------------------------------------------
@@ -466,8 +464,7 @@ This is a perfectly valid solution, but Rails provides a less verbose alternativ
----------------------------------------------------------------------------
<%= options_from_collection_for_select(City.all, :id, :name) %>
----------------------------------------------------------------------------
-
-As the name implies, this only generates option tags. To generate a working select box you would need to use it in conjunction with `select_tag`, just as you would with `options_for_select`. A method to go along with it is `collection_select`:
+As the name implies, this only generates option tags. To generate a working select box you would need to use it in conjunction with `select_tag`, just as you would with `options_for_select`. When working with model objects, just as `select` combines `select_tag` and `options_for_select`, `collection_select` combines `select_tag` with `options_from_collection_for_select`.
----------------------------------------------------------------------------
<%= collection_select(:person, :city_id, City.all, :id, :name) %>
@@ -475,13 +472,18 @@ As the name implies, this only generates option tags. To generate a working sele
To recap, `options_from_collection_for_select` is to `collection_select` what `options_for_select` is to `select`.
+[NOTE]
+=============================
+Pairs passed to `options_for_select` should have the name first and the id second, however with `options_from_collection_for_select` the first argument is the value method and the second the text method.
+=============================
+
Time zone and country select
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-To leverage time zone support in Rails, you 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 `collection_select`, but you can simply use the `time_zone_select` helper that already wraps this:
+To leverage time zone support in Rails, you have to ask your users what time zone they are in. Doing so would require generating select options from a list of pre-defined TimeZone objects using `collection_select`, but you can simply use the `time_zone_select` helper that already wraps this:
----------------------------------------------------------------------------
-<%= time_zone_select(:person, :city_id) %>
+<%= time_zone_select(:person, :time_zone) %>
----------------------------------------------------------------------------
There is also `time_zone_options_for_select` 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.
@@ -493,49 +495,49 @@ Using Date and Time Form Helpers
The date and time helpers differ from all the other form helpers in two important respects:
-1. Unlike other attributes you might typically have, dates and times are not representable by a single input element. Instead you have several, one for each component (year, month, day etc...). So in particular, there is no single value in your params hash with your date or time.
-2. Other helpers use the _tag suffix to indicate whether a helper is a barebones helper or one that operates on model objects. With dates and times, `select\_date`, `select\_time` and `select_datetime` are the barebones helpers, `date_select`, `time_select` and `datetime_select` are the equivalent model object helpers
+1. Dates and times are not representable by a single input element. Instead you have several, one for each component (year, month, day etc.) and so there is no single value in your `params` hash with your date or time.
+2. Other helpers use the _tag suffix to indicate whether a helper is a barebones helper or one that operates on model objects. With dates and times, `select_date`, `select_time` and `select_datetime` are the barebones helpers, `date_select`, `time_select` and `datetime_select` are the equivalent model object helpers.
-Both of these families of helpers will create a series of select boxes for the different components (year, month, day etc...).
+Both of these families of helpers will create a series of select boxes for the different components (year, month, day etc.).
Barebones helpers
~~~~~~~~~~~~~~~~~
The `select_*` family of helpers take as their first argument an instance of Date, Time or DateTime that is used as the currently selected value. You may omit this parameter, in which case the current date is used. For example
-----------
-<%= select_date Date::today, :prefix => :start_date %>
+<%= select_date Date.today, :prefix => :start_date %>
-----------
-outputs (with the actual option values omitted for brevity)
+outputs (with actual option values omitted for brevity)
-----------
<select id="start_date_year" name="start_date[year]"> ... </select>
<select id="start_date_month" name="start_date[month]"> ... </select>
<select id="start_date_day" name="start_date[day]"> ... </select>
-----------
-The above inputs would result in `params[:start_date]` being a hash with keys :year, :month, :day. To get an actual Time or Date object you would have to extract these values and pass them to the appropriate constructor, for example
+The above inputs would result in `params[:start_date]` being a hash with keys `:year`, `:month`, `:day`. To get an actual Time or Date object you would have to extract these values and pass them to the appropriate constructor, for example
-----------
-Date::civil(params[:start_date][:year].to_i, params[:start_date][:month].to_i, params[:start_date][:day].to_i)
+Date.civil(params[:start_date][:year].to_i, params[:start_date][:month].to_i, params[:start_date][:day].to_i)
-----------
-The :prefix option controls where in the params hash the date components will be placed. Here it was set to `start_date`, if omitted it will default to `date`.
+The `:prefix` option is the key used to retrieve the hash of date components from the `params` hash. Here it was set to `start_date`, if omitted it will default to `date`.
Model object helpers
~~~~~~~~~~~~~~~~~~~~
-`select_date` does not work well with forms that update or create Active Record objects as Active Record expects each element of the params hash to correspond to one attribute.
-The model object helpers for dates and times submit parameters with special names. When Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type. For example
+`select_date` does not work well with forms that update or create Active Record objects as Active Record expects each element of the `params` hash to correspond to one attribute.
+The model object helpers for dates and times submit parameters with special names, when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type. For example:
---------------
<%= date_select :person, :birth_date %>
---------------
-outputs (with the actual option values omitted for brevity)
+outputs (with actual option values omitted for brevity)
--------------
<select id="person_birth_date_1i" name="person[birth_date(1i)]"> ... </select>
<select id="person_birth_date_2i" name="person[birth_date(2i)]"> ... </select>
<select id="person_birth_date_3i" name="person[birth_date(3i)]"> ... </select>
--------------
-which results in a params hash like
+which results in a `params` hash like
--------------
{:person => {'birth_date(1i)' => '2008', 'birth_date(2i)' => '11', 'birth_date(3i)' => '22'}}
--------------
-When this is passed to `Person.new`, Active Record spots that these parameters should all be used to construct the `birth_date` attribute and uses the suffixed information to determine in which order it should pass these parameters to functions such as `Date::civil`.
+When this is passed to `Person.new` (or `update_attributes`), Active Record spots that these parameters should all be used to construct the `birth_date` attribute and uses the suffixed information to determine in which order it should pass these parameters to functions such as `Date.civil`.
Common options
~~~~~~~~~~~~~~
@@ -545,9 +547,23 @@ As a rule of thumb you should be using `date_select` when working with model obj
NOTE: In many cases the built in date pickers are clumsy as they do not aid the user in working out the relationship between the date and the day of the week.
+Individual components
+~~~~~~~~~~~~~~~~~~~~~
+
+Occasionally you need to display just a single date component such as a year or a month. Rails provides a series of helpers for this, one for each component `select_year`, `select_month`, `select_day`, `select_hour`, `select_minute`, `select_second`. These helpers are fairly straightforward. By default they will generate a input named after the time component (for example "year" for `select_year`, "month" for `select_month` etc.) although this can be overriden with the `:field_name` option. The `:prefix` option works in the same way that it does for `select_date` and `select_time` and has the same default value.
+
+The first parameter specifies which value should be selected and can either be an instance of a Date, Time or DateTime, in which case the relevant component will be extracted, or a numerical value. For example
+
+---------------
+<%= select_year(2009) %>
+<%= select_year(Time.now) %>
+---------------
+
+will produce the same output if the current year is 2009 and the value chosen by the user can be retrieved by `params[:date][:year]`.
+
Uploading Files
--------------
-A common task is uploading some sort of file, whether it's a picture of a person or a CSV file containing data to process. The most important thing to remember with file uploads is that the form's encoding *MUST* be set to multipart/form-data. If you forget to do this the file will not be uploaded. This can be done by passing `:multi_part => true` as an HTML option. This means that in the case of `form_tag` it must be passed in the second options hash and in the case of `form_for` inside the `:html` hash.
+A common task is uploading some sort of file, whether it's a picture of a person or a CSV file containing data to process. The most important thing to remember with file uploads is that the form's encoding *MUST* be set to "multipart/form-data". If you forget to do this the file will not be uploaded. This can be done by passing `:multi_part => true` as an HTML option. This means that in the case of `form_tag` it must be passed in the second options hash and in the case of `form_for` inside the `:html` hash.
The following two forms both upload a file.
-----------
@@ -563,7 +579,7 @@ Rails provides the usual pair of helpers: the barebones `file_field_tag` and the
What gets uploaded
~~~~~~~~~~~~~~~~~~
-The object in the params hash is an instance of a subclass of IO. Depending on the size of the uploaded file it may in fact be a StringIO or an instance of File backed by a temporary file. In both cases the object will have an `original_filename` attribute containing the name the file had on the user's computer and a `content_type` attribute containing the MIME type of the uploaded file. The following snippet saves the uploaded content in `#\{RAILS_ROOT\}/public/uploads` under the same name as the original file (assuming the form was the one in the previous example).
+The object in the `params` hash is an instance of a subclass of IO. Depending on the size of the uploaded file it may in fact be a StringIO or an instance of File backed by a temporary file. In both cases the object will have an `original_filename` attribute containing the name the file had on the user's computer and a `content_type` attribute containing the MIME type of the uploaded file. The following snippet saves the uploaded content in `#\{Rails.root\}/public/uploads` under the same name as the original file (assuming the form was the one in the previous example).
[source, ruby]
-----------------
@@ -581,15 +597,15 @@ NOTE: If the user has not selected a file the corresponding parameter will be an
Dealing with Ajax
~~~~~~~~~~~~~~~~~
-Unlike other forms making an asynchronous file upload form is not as simple as replacing `form_for` with `remote_form_for`. With an AJAX form the serialization is done by javascript running inside the browser and since javascript cannot read files from your hard drive the file cannot be uploaded. The most common workaround is to use an invisible iframe that serves as the target for the form submission.
+Unlike other forms making an asynchronous file upload form is not as simple as replacing `form_for` with `remote_form_for`. With an Ajax form the serialization is done by JavaScript running inside the browser and since JavaScript cannot read files from your hard drive the file cannot be uploaded. The most common workaround is to use an invisible iframe that serves as the target for the form submission.
Customising Form Builders
-------------------------
-As mentioned previously the object yielded by `form_for` and `fields_for` is an instance of FormBuilder (or a subclass thereof). Form builders encapsulate the notion of displaying a form elements for a single object. While you can of course write helpers for your forms in the usual way you can also subclass FormBuilder and add the helpers there. For example
+As mentioned previously the object yielded by `form_for` and `fields_for` is an instance of FormBuilder (or a subclass thereof). Form builders encapsulate the notion of displaying form elements for a single object. While you can of course write helpers for your forms in the usual way you can also subclass FormBuilder and add the helpers there. For example
----------
-<% form_for @person do |f| %>
+<% form_for @person do |f| %>
<%= text_field_with_label f, :first_name %>
<% end %>
----------
@@ -604,7 +620,7 @@ by defining a LabellingFormBuilder class similar to the following:
[source, ruby]
-------
class LabellingFormBuilder < FormBuilder
- def text_field attribute, options={}
+ def text_field(attribute, options={})
label(attribute) + text_field(attribute, options)
end
end
@@ -615,36 +631,35 @@ The form builder used also determines what happens when you do
------
<%= render :partial => f %>
------
-If `f` is an instance of FormBuilder then this will render the 'form' partial, setting the partial's object to the form builder. If the form builder is of class LabellingFormBuilder then the 'labelling_form' partial would be rendered instead.
+If `f` is an instance of FormBuilder then this will render the `form` partial, setting the partial's object to the form builder. If the form builder is of class LabellingFormBuilder then the `labelling_form` partial would be rendered instead.
Understanding Parameter Naming Conventions
-----------------------------------------
[[parameter_names]]
-As you've seen in the previous sections, values from forms can appear either at the top level of the params hash or may appear nested in another hash. For example in a standard create
-action for a Person model, `params[:model]` would usually be a hash of all the attributes for the person to create. The params hash can also contain arrays, arrays of hashes and so on.
+As you've seen in the previous sections, values from forms can be at the top level of the `params` hash or nested in another hash. For example in a standard `create`
+action for a Person model, `params[:model]` would usually be a hash of all the attributes for the person to create. The `params` hash can also contain arrays, arrays of hashes and so on.
-Fundamentally HTML forms don't know about any sort of structured data, all they generate is name-value pairs. The arrays and hashes you see in your application are the result of some parameter naming conventions that Rails uses.
+Fundamentally HTML forms don't know about any sort of structured data, all they generate is name-value pairs, where pairs are just plain strings. The arrays and hashes you see in your application are the result of some parameter naming conventions that Rails uses.
[TIP]
========================
You may find you can try out examples in this section faster by using the console to directly invoke Rails' parameter parser. For example
-------------
-ActionController::RequestParser.parse_query_parameters "name=fred&phone=0123456789"
-#=> {"name"=>"fred", "phone"=>"0123456789"}
+ActionController::UrlEncodedPairParser.parse_query_parameters "name=fred&phone=0123456789"
+# => {"name"=>"fred", "phone"=>"0123456789"}
-------------
========================
Basic structures
~~~~~~~~~~~~~~~
-The two basic structures are arrays and hashes. Hashes mirror the syntax used for accessing the value in the params. For example if a form contains
+The two basic structures are arrays and hashes. Hashes mirror the syntax used for accessing the value in `params`. For example if a form contains
-----------------
<input id="person_name" name="person[name]" type="text" value="Henry"/>
-----------------
-the params hash will contain
+the `params` hash will contain
-[source, ruby]
-----------------
{'person' => {'name' => 'Henry'}}
-----------------
@@ -654,9 +669,8 @@ Hashes can be nested as many levels as required, for example
------------------
<input id="person_address_city" name="person[address][city]" type="text" value="New York"/>
------------------
-will result in the params hash being
+will result in the `params` hash being
-[source, ruby]
-----------------
{'person' => {'address' => {'city' => 'New York'}}}
-----------------
@@ -677,22 +691,21 @@ We can mix and match these two concepts. For example, one element of a hash migh
<input name="addresses[][line2]" type="text"/>
<input name="addresses[][city]" type="text"/>
-----------------
-This would result in `params[:addresses]` being an array of hashes with keys `line1`, `line2` and `city`. Rails decides to start accumulating values in a new hash whenever it encounters a input name that already exists in the current hash.
+This would result in `params[:addresses]` being an array of hashes with keys `line1`, `line2` and `city`. Rails decides to start accumulating values in a new hash whenever it encounters an input name that already exists in the current hash.
-The one restriction is that although hashes can be nested arbitrarily deep then can be only one level of "arrayness". Frequently arrays can be usually replaced by hashes, for example instead of having an array of model objects one can have a hash of model objects keyed by their id.
+There's a restriction, however, while hashes can be nested arbitrarily, only one level of "arrayness" is allowed. Arrays can be usually replaced by hashes, for example instead of having an array of model objects one can have a hash of model objects keyed by their id, an array index or some other parameter.
[WARNING]
-Array parameters do not play well with the `check_box` helper. According to the HTML specification unchecked checkboxes submit no value. However it is often convenient for a checkbox to always submit a value. The `check_box` helper fakes this by creating a second hidden input with the same name. If the checkbox is unchecked only the hidden input is submitted. If the checkbox is checked then both are submitted but the value submitted by the checkbox takes precedence. When working with array parameters this duplicate submission will confuse Rails since duplicate input names are how it decides when to start a new hash. It is preferable to either use `check_box_tag` or to use hashes instead of arrays.
+Array parameters do not play well with the `check_box` helper. According to the HTML specification unchecked checkboxes submit no value. However it is often convenient for a checkbox to always submit a value. The `check_box` helper fakes this by creating a second hidden input with the same name. If the checkbox is unchecked only the hidden input is submitted and if it is checked then both are submitted but the value submitted by the checkbox takes precedence. When working with array parameters this duplicate submission will confuse Rails since duplicate input names are how it decides when to start a new array element. It is preferable to either use `check_box_tag` or to use hashes instead of arrays.
Using form helpers
~~~~~~~~~~~~~~~~~
-The previous sections did not use the Rails form helpers at all. While you can craft the input names yourself and pass them directly to helpers such as `text_field_tag` Rails also provides higher level support. The two tools at your disposal here are the name parameter to `form_for`/`fields_for` and the `:index` option.
-
-You might want to render a form with a set of edit fields for each of a person's addresses. Something a little like this will do the trick
+The previous sections did not use the Rails form helpers at all. While you can craft the input names yourself and pass them directly to helpers such as `text_field_tag` Rails also provides higher level support. The two tools at your disposal here are the name parameter to `form_for` and `fields_for` and the `:index` option that helpers take.
+You might want to render a form with a set of edit fields for each of a person's addresses. For example:
--------
<% form_for @person do |person_form| %>
- <%= person_form.text_field :name%>
+ <%= person_form.text_field :name %>
<% for address in @person.addresses %>
<% person_form.fields_for address, :index => address do |address_form|%>
<%= address_form.text_field :city %>
@@ -700,7 +713,7 @@ You might want to render a form with a set of edit fields for each of a person's
<% end %>
<% end %>
--------
-Assuming our person had two addresses, with ids 23 and 45 this would create output similar to this:
+Assuming the person had two addresses, with ids 23 and 45 this would create output similar to this:
--------
<form action="/people/1" class="edit_person" id="edit_person_1" method="post">
<input id="person_name" name="person[name]" size="30" type="text" />
@@ -708,14 +721,13 @@ Assuming our person had two addresses, with ids 23 and 45 this would create outp
<input id="person_address_45_city" name="person[address][45][city]" size="30" type="text" />
</form>
--------
-This will result in a params hash that looks like
+This will result in a `params` hash that looks like
-[source, ruby]
--------
-{'person' => {'name' => 'Bob', 'address' => { '23' => {'city' => 'Paris'}, '45' => {'city' => 'London'} }}}
+{'person' => {'name' => 'Bob', 'address' => {'23' => {'city' => 'Paris'}, '45' => {'city' => 'London'}}}}
--------
-Rails knows that all these inputs should be part of the person hash because you called `fields_for` on the first form builder. By specifying an `:index` option you're telling rails that instead of naming the inputs `person[address][city]` it should insert that index surrounded by [] between the address and the city. If you pass an Active Record object as we did then Rails will call `to_param` on it, which by default returns the database id. This is often useful it is then easy to locate which Address record should be modified but you could pass numbers with some other significance, strings or even nil (which will result in an array parameter being created).
+Rails knows that all these inputs should be part of the person hash because you called `fields_for` on the first form builder. By specifying an `:index` option you're telling rails that instead of naming the inputs `person[address][city]` it should insert that index surrounded by [] between the address and the city. If you pass an Active Record object as we did then Rails will call `to_param` on it, which by default returns the database id. This is often useful as it is then easy to locate which Address record should be modified. You can pass numbers with some other significance, strings or even `nil` (which will result in an array parameter being created).
To create more intricate nestings, you can specify the first part of the input name (`person[address]` in the previous example) explicitly, for example
--------
@@ -727,7 +739,7 @@ will create inputs like
--------
<input id="person_address_primary_1_city" name="person[address][primary][1][city]" size="30" type="text" value="bologna" />
--------
-As a general rule the final input name is the concatenation of the name given to `fields_for`/`form_for`, the index value and the name of the attribute. You can also pass an `:index` option directly to helpers such as `text_field`, but usually it is less repetitive to specify this at the form builder level rather than on individual input controls.
+As a general rule the final input name is the concatenation of the name given to `fields_for`/`form_for`, the index value and the name of the attribute. You can also pass an `:index` option directly to helpers such as `text_field`, but it is usually less repetitive to specify this at the form builder level rather than on individual input controls.
As a shortcut you can append [] to the name and omit the `:index` option. This is the same as specifing `:index => address` so
--------
@@ -740,7 +752,7 @@ produces exactly the same output as the previous example.
Building Complex forms
----------------------
-Many apps grow beyond simple forms editing a single object. For example when creating a Person instance you might want to allow the user to (on the same form) create multiple address records (home, work etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary. While this guide has shown you all the pieces necessary to handle this, Rails does not yet have a standard end-to-end way of accomplishing this, but many have come up with viable approaches. These include:
+Many apps grow beyond simple forms editing a single object. For example when creating a Person you might want to allow the user to (on the same form) create multiple address records (home, work, etc.). When later editing that person the user should be able to add, remove or amend addresses as necessary. While this guide has shown you all the pieces necessary to handle this, Rails does not yet have a standard end-to-end way of accomplishing this, but many have come up with viable approaches. These include:
* Ryan Bates' series of railscasts on http://railscasts.com/episodes/75[complex forms]
* Handle Multiple Models in One Form from http://media.pragprog.com/titles/fr_arr/multiple_models_one_form.pdf[Advanced Rails Recipes]
diff --git a/railties/doc/guides/source/i18n.txt b/railties/doc/guides/source/i18n.txt
index 2638807761..4465a77289 100644
--- a/railties/doc/guides/source/i18n.txt
+++ b/railties/doc/guides/source/i18n.txt
@@ -1,9 +1,25 @@
The Rails Internationalization (I18n) API
=========================================
-The Ruby I18n (shorthand for _internationalization_) gem which is shipped with Ruby on Rails (starting from Rails 2.2) provides an easy-to-use and extensible framework for translating your application to a single custom language other than English or providing multi-language support in your application.
+The Ruby I18n (shorthand for _internationalization_) gem which is shipped with Ruby on Rails (starting from Rails 2.2) provides an easy-to-use and extensible framework for *translating your application to a single custom language* other than English or for *providing multi-language support* in your application.
-NOTE: The Ruby I18n framework provides you with all neccessary means for internationalization/localization of your Rails application. You may, however, use any of various plugins and extensions available. See Rails http://rails-i18n.org/wiki[I18n Wiki] for more information.
+The process of "internationalization" usually means to abstract all strings and other locale specific bits (such as date or currency formats) out of your application. The process of "localization" means to provide translations and localized formats for these bits. <<1>>
+
+So, in the process of _internationalizing_ your Rails application you have to:
+
+* Ensure you have support for i18n
+* Tell Rails where to find locale dictionaries
+* Tell Rails how to set, preserve and switch locale
+
+In the process of _localizing_ your application you'll probably want to do following three things:
+
+* Replace or supplement Rail's default locale -- eg. date and time formats, month names, ActiveRecord model names, etc
+* Abstract texts in your application into keyed dictionaries -- eg. flash messages, static texts in your views, etc
+* Store the resulting dictionaries somewhere
+
+This guide will walk you through the I18n API and contains a tutorial how to internationalize a Rails application from the start.
+
+NOTE: The Ruby I18n framework provides you with all neccessary means for internationalization/localization of your Rails application. You may, however, use any of various plugins and extensions available, which add additional functionality or features. See Rails http://rails-i18n.org/wiki[I18n Wiki] for more information.
== How I18n in Ruby on Rails works
@@ -78,6 +94,8 @@ This means, that in the +:en+ locale, the key _hello_ will map to _Hello world_
The I18n library will use *English* as a *default locale*, ie. if you don't set a different locale, +:en+ will be used for looking up translations.
+NOTE: The i18n library takes *pragmatic approach* to locale keys (after http://groups.google.com/group/rails-i18n/browse_thread/thread/14dede2c7dbe9470/80eec34395f64f3c?hl=en[some discussion]), including only the _locale_ ("language") part, like +:en+, +:pl+, not the _region_ part, like +:en-US+ or +:en-UK+, which are traditionally used for separating "languages" and "regional setting" or "dialects". (For instance, in the +:en-US+ locale you would have $ as a currency symbol, while in +:en-UK+, you would have €. Also, insults would be different in American and British English :) Reason for this pragmatic approach is that most of the time, you usually care about making your application available in different "languages", and working with locales is much simpler this way. However, nothing stops you from separating regional and other settings in the traditional way. In this case, you could eg. inherit from the default +en+ locale and then provide UK specific settings in a +:en-UK+ dictionary.
+
The *translations load path* (+I18n.load_path+) is just a Ruby Array of paths to your translation files that will be loaded automatically and available in your application. You can pick whatever directory and translation file naming scheme makes sense for you.
NOTE: The backend will lazy-load these translations when a translation is looked up for the first time. This makes it possible to just swap the backend with something else even after translations have already been announced.
@@ -116,7 +134,7 @@ If you want to translate your Rails application to a *single language other than
However, you would probably like to *provide support for more locales* in your application. In such case, you need to set and pass the locale between requests.
-WARNING: You may be tempted to store choosed locale in a _session_ or a _cookie_. *Do not do so*. The locale should be transparent and a part of the URL. This way you don't break people's basic assumptions about the web itself: if you send a URL of some page to a friend, she should see the same page, same content. A fancy word for this would be that you're being http://en.wikipedia.org/wiki/Representational_State_Transfer[_RESTful_]. There may be some exceptions to this rule, which are discussed below.
+WARNING: You may be tempted to store choosed locale in a _session_ or a _cookie_. *Do not do so*. The locale should be transparent and a part of the URL. This way you don't break people's basic assumptions about the web itself: if you send a URL of some page to a friend, she should see the same page, same content. A fancy word for this would be that you're being http://en.wikipedia.org/wiki/Representational_State_Transfer[_RESTful_]. Read more about RESTful approach in http://www.infoq.com/articles/rest-introduction[Stefan Tilkov's articles]. There may be some exceptions to this rule, which are discussed below.
The _setting part_ is easy. You can set locale in a +before_filter+ in the ApplicationController like this:
@@ -125,17 +143,17 @@ The _setting part_ is easy. You can set locale in a +before_filter+ in the Appli
before_filter :set_locale
def set_locale
# if params[:locale] is nil then I18n.default_locale will be used
- I18n.locale = params[:locale]
+ I18n.locale = params[:locale]
end
-------------------------------------------------------
-This requires you to pass the locale as a URL query parameter as in +http://example.com/books?locale=pt+. (This is eg. Google's approach). So +http://localhost:3000?locale=pt+ will load the Portugese localization, whereas +http://localhost:3000?locale=de+ would load the German localization, and so on.
+This requires you to pass the locale as a URL query parameter as in +http://example.com/books?locale=pt+. (This is eg. Google's approach). So +http://localhost:3000?locale=pt+ will load the Portugese localization, whereas +http://localhost:3000?locale=de+ would load the German localization, and so on. You may skip the next section and head over to the *Internationalize your application* section, if you want to try things out by manually placing locale in the URL and reloading the page.
Of course, you probably don't want to manually include locale in every URL all over your application, or want the URLs look differently, eg. the usual +http://example.com/pt/books+ versus +http://example.com/en/books+. Let's discuss the different options you have.
IMPORTANT: Following examples rely on having locales loaded into your application available as an array of strings like +["en", "es", "gr"]+. This is not inclued in current version of Rails 2.2 -- forthcoming Rails version 2.3 will contain easy accesor +available_locales+. (See http://github.com/svenfuchs/i18n/commit/411f8fe7[this commit] and background at http://rails-i18n.org/wiki/pages/i18n-available_locales[Rails I18n Wiki].)
-We have to include support for getting available locales manually in an initializer like this:
+So, for having available locales easily available in Rails 2.2, we have to include this support manually in an initializer, like this:
[source, ruby]
-------------------------------------------------------
@@ -172,7 +190,7 @@ end
=== Setting locale from the domain name
-One option you have is to set the locale from the domain name, where your application runs. For example, we want +www.example.com+ to load English (or default) locale, and +www.example.es+ to load Spanish locale. Thus the _top-level domain name_ is used for locale setting. This has several advantages:
+One option you have is to set the locale from the domain name where your application runs. For example, we want +www.example.com+ to load English (or default) locale, and +www.example.es+ to load Spanish locale. Thus the _top-level domain name_ is used for locale setting. This has several advantages:
* Locale is an _obvious_ part of the URL
* People intuitively grasp in which language the content will be displayed
@@ -213,22 +231,107 @@ def extract_locale_from_subdomain
end
-------------------------------------------------------
+If your application includes a locale switching menu, you would then have something like this in it:
+
+[source, ruby]
+-------------------------------------------------------
+link_to("Deutsch", "#{APP_CONFIG[:deutsch_website_url]}#{request.env['REQUEST_URI']}")
+-------------------------------------------------------
+
+assuming you would set +APP_CONFIG[:deutsch_website_url]+ to some value like +http://www.application.de+.
+
+This solution has aforementioned advantages, however, you may not be able or may not want to provide different localizations ("language versions") on different domains. The most obvious solution would be to include locale code in the URL params (or request path).
+
=== Setting locale from the URL params
-* TODO : Based on *+default_url options+*, http://github.com/karmi/test_default_url_options/blob/master/app/controllers/application.rb#L22-26
+Most usual way of setting (and passing) the locale would be to include it in URL params, as we did in the +I18n.locale = params[:locale]+ _before_filter_ in the first example. We would like to have URLs like +www.example.com/books?locale=ja+ or +www.example.com/ja/books+ in this case.
-* TODO : Discussion of plugins (translate_routes and routing_filter)
+This approach has almost the same set of advantages as setting the locale from domain name: namely that it's RESTful and in accord with rest of the World Wide Web. It does require a little bit more work to implement, though.
+Getting the locale from +params+ and setting it accordingly is not hard; including it in every URL and thus *passing it through the requests* is. To include an explicit option in every URL (eg. +link_to( books_url(:locale => I18n.locale) )+) would be tedious and probably impossible, of course.
-TIP: For setting locale from URL see http://rails-i18n.org/wiki/pages/how-to-encode-the-current-locale-in-the-url[How to encode the current locale in the URL] in the Rails i18n Wiki.
+Rails contains infrastructure for "centralizing dynamic decisions about the URLs" in its http://api.rubyonrails.org/classes/ActionController/Base.html#M000515[+*ApplicationController#default_url_options*+], which is useful precisely in this scenario: it enables us to set "defaults" for http://api.rubyonrails.org/classes/ActionController/Base.html#M000503[+url_for+] and helper methods dependent on it (by implementing/overriding this method).
-Now you've initialized I18n support for your application and told it which locale should be used. With that in place you're now ready for the really interesting stuff.
+We can include something like this in our ApplicationController then:
-== Internationalize your application
+[source, ruby]
+-------------------------------------------------------
+# app/controllers/application_controller.rb
+def default_url_options(options={})
+ logger.debug "default_url_options is passed options: #{options.inspect}\n"
+ { :locale => I18n.locale }
+end
+-------------------------------------------------------
+
+Every helper method dependent on +url_for+ (eg. helpers for named routes like +root_path+ or +root_url+, resource routes like +books_path+ or +books_url+, etc.) will now *automatically include the locale in the query string*, like this: +http://localhost:3001/?locale=ja+.
+
+You may be satisfied with this. It does impact the readability of URLs, though, when the locale "hangs" at the end of every URL in your application. Moreover, from the architectural standpoint, locale is usually hierarchically above the other parts of application domain: and URLs should reflect this.
+
+You probably want URLs look like this: +www.example.com/en/books+ (which loads English locale) and +www.example.com/nl/books+ (which loads Netherlands locale). This is achievable with the "over-riding +default_url_options+" strategy from above: you just have to set up your routes with http://api.rubyonrails.org/classes/ActionController/Resources.html#M000354[+path_prefix+] option in this way:
+
+[source, ruby]
+-------------------------------------------------------
+# config/routes.rb
+map.resources :books, :path_prefix => '/:locale'
+-------------------------------------------------------
+
+Now, when you call +books_path+ method you should get +"/en/books"+ (for the default locale). An URL like +http://localhost:3001/nl/books+ should load the Netherlands locale, then, and following calls to +books_path+ should return +"/nl/books"+ (because the locale changed).
-The process of "internationalization" usually means to abstract all strings and other locale specific bits out of your application. The process of "localization" means to then provide translations and localized formats for these bits. <<1>>
+Of course, you need to take special care of root URL (usually "homepage" or "dashboard") of your application. An URL like +http://localhost:3001/nl+ will not work automatically, because the +map.root :controller => "dashboard"+ declaration in your +routes.rb+ doesn't take locale into account. (And rightly so. There's only one "root" URL.)
-So, let's internationalize something. You most probably have something like this in one of your applications:
+You would probably need to map URLs like these:
+
+[source, ruby]
+-------------------------------------------------------
+# config/routes.rb
+map.dashboard '/:locale', :controller => "dashboard"
+-------------------------------------------------------
+
+Do take special care about the *order of your routes*, so this route declaration does not "eat" other ones. (You may want to add it directly before the +map.root+ declaration.)
+
+IMPORTANT: This solution has currently one rather big *downside*. Due to the _default_url_options_ implementation, you have to pass the +:id+ option explicitely, like this: +link_to 'Show', book_url(:id => book)+ and not depend on Rails' magic in code like +link_to 'Show', book+. If this should be a problem, have a look on two plugins which simplify working with routes in this way: Sven Fuchs's http://github.com/svenfuchs/routing-filter/tree/master[_routing_filter_] and Raul Murciano's http://github.com/raul/translate_routes/tree/master[_translate_routes_]. See also the page http://rails-i18n.org/wiki/pages/how-to-encode-the-current-locale-in-the-url[How to encode the current locale in the URL] in the Rails i18n Wiki.
+
+=== Setting locale from the client supplied information
+
+In specific cases, it would make sense to set locale from client supplied information, ie. not from URL. This information may come for example from users' preffered language (set in their browser), can be based on users' geographical location inferred from their IP, or users can provide it simply by choosing locale in your application interface and saving it to their profile. This approach is more suitable for web-based applications or services, not for websites -- see the box about _sessions_, _cookies_ and RESTful architecture above.
+
+
+==== Using Accept-Language
+
+One source of client supplied information would be an +Accept-Language+ HTTP header. People may http://www.w3.org/International/questions/qa-lang-priorities[set this in their browser] or other clients (such as _curl_).
+
+A trivial implementation of using +Accept-Language+ header would be:
+
+[source, ruby]
+-------------------------------------------------------
+def set_locale
+ logger.debug "* Accept-Language: #{request.env['HTTP_ACCEPT_LANGUAGE']}"
+ I18n.locale = extract_locale_from_accept_language_header
+ logger.debug "* Locale set to '#{I18n.locale}'"
+end
+private
+def extract_locale_from_accept_language_header
+ request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
+end
+-------------------------------------------------------
+
+Of course, in production environment you would need much robust code, and could use a plugin such as Iaian Hecker's http://github.com/iain/http_accept_language[http_accept_language].
+
+==== Using GeoIP (or similar) database
+
+Another way of choosing the locale from client's information would be to use a database for mapping client IP to region, such as http://www.maxmind.com/app/geolitecountry[GeoIP Lite Country]. The mechanics of the code would be very similar to the code above -- you would need to query database for user's IP, and lookup your preffered locale for the country/region/city returned.
+
+==== User profile
+
+You can also provide users of your application with means to set (and possibly over-ride) locale in your application interface, as well. Again, mechanics for this approach would be very similar to the code above -- you'd probably let users choose a locale from a dropdown list and save it to their profile in database. Then you'd set the locale to this value.
+
+== Internationalizing your application
+
+OK! Now you've initialized I18n support for your Ruby on Rails application and told it which locale should be used and how to preserve it between requests. With that in place, you're now ready for the really interesting stuff.
+
+Let's _internationalize_ our application, ie. abstract every locale-specific parts, and that _localize_ it, ie. provide neccessary translations for these abstracts.
+
+You most probably have something like this in one of your applications:
[source, ruby]
-------------------------------------------------------
@@ -253,7 +356,7 @@ image:images/i18n/demo_untranslated.png[rails i18n demo untranslated]
=== Adding Translations
-Obviously there are two strings that are localized to English. In order to internationalize this code replace these strings with calls to Rails' #t helper with a key that makes sense for the translation:
+Obviously there are *two strings that are localized to English*. In order to internationalize this code, *replace these strings* with calls to Rails' +#t+ helper with a key that makes sense for the translation:
[source, ruby]
-------------------------------------------------------
@@ -269,13 +372,13 @@ end
<p><%= flash[:notice] %></p>
-------------------------------------------------------
-When you now render this view it will show an error message that tells you that the translations for the keys :hello_world and :hello_flash are missing.
+When you now render this view, it will show an error message which tells you that the translations for the keys +:hello_world+ and +:hello_flash+ are missing.
image:images/i18n/demo_translation_missing.png[rails i18n demo translation missing]
-NOTE: Rails adds a +t+ (+translate+) helper method to your views so that you do not need to spell out +I18n.t+ all the time. Additionally this helper will catch missing translations and wrap the resulting error message into a &lt;span class="translation_missing"&gt;.
+NOTE: Rails adds a +t+ (+translate+) helper method to your views so that you do not need to spell out +I18n.t+ all the time. Additionally this helper will catch missing translations and wrap the resulting error message into a +<span class="translation_missing">+.
-So let's add the missing translations (i.e. do the "localization" part):
+So let's add the missing translations into the dictionary files (i.e. do the "localization" part):
[source, ruby]
-------------------------------------------------------
@@ -290,19 +393,19 @@ pirate:
hello_flash: Ahoy Flash
-------------------------------------------------------
-There you go. Because you haven't changed the default_locale I18n will use English. Your application now shows:
+There you go. Because you haven't changed the default_locale, I18n will use English. Your application now shows:
image:images/i18n/demo_translated_en.png[rails i18n demo translated to english]
-And when you change the URL to pass the pirate locale you get:
+And when you change the URL to pass the pirate locale (+http://localhost:3000?locale=pirate+), you'll get:
image:images/i18n/demo_translated_pirate.png[rails i18n demo translated to pirate]
-NOTE You need to restart the server when you add new locale files.
+NOTE: You need to restart the server when you add new locale files.
=== Adding Date/Time formats
-Ok, let's add a timestamp to the view so we can demo the date/time localization feature as well. To localize the time format you pass the Time object to I18n.l or (preferably) use Rails' #l helper. You can pick a format by passing the :format option, by default the :default format is used.
+OK! Now let's add a timestamp to the view, so we can demo the *date/time localization* feature as well. To localize the time format you pass the Time object to +I18n.l+ or (preferably) use Rails' +#l+ helper. You can pick a format by passing the +:format+ option -- by default the +:default+ format is used.
[source, ruby]
-------------------------------------------------------
@@ -327,17 +430,53 @@ So that would give you:
image:images/i18n/demo_localized_pirate.png[rails i18n demo localized time to pirate]
-NOTE Right now you might need to add some more date/time formats in order to make the I18n backend work as expected. See the http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale[rails-i18n repository] for starting points.
+TIP: Right now you might need to add some more date/time formats in order to make the I18n backend work as expected. Of course, there's a great chance that somebody already did all the work by *translating Rails's defaults for your locale*. See the http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale[rails-i18n repository at Github] for an archive of various locale files. When you put such file(s) in +config/locale/+ directory, they will automatically ready for use.
+
+=== Organization of locale files
+When you are using the default SimpleStore, shipped with the i18n library, you store dictionaries in plain-text files on the disc. Putting translations for all parts of your application in one file per locale could be hard to manage. You can store these files in a hierarchy which makes sense to you.
+
+For example, your +config/locale+ directory could look like this:
+
+-------------------------------------------------------
+|-defaults
+|---es.rb
+|---en.rb
+|-models
+|---book
+|-----es.rb
+|-----en.rb
+|-views
+|---defaults
+|-----es.rb
+|-----en.rb
+|---books
+|-----es.rb
+|-----en.rb
+|---users
+|-----es.rb
+|-----en.rb
+|---navigation
+|-----es.rb
+|-----en.rb
+-------------------------------------------------------
+
+This way, you can separate model and model attribute names from text inside views, and all of this from the "defaults" (eg. date and time formats).
+
+Other stores for the i18n library could provide different means of such separation.
+
+Do check the http://rails-i18n.org/wiki[Rails i18n Wiki] for list of tools available for managing translations.
== Overview of the I18n API features
-The following purposes are covered:
+You should have good understanding of using the i18n library now, knowing all neccessary aspects of internationalizing a basic Rails application. In the following chapters, we'll cover it's features in more depth.
+
+Covered are features like these:
-* lookup translations
-* interpolate data into translations
-* pluralize translations
-* localize dates, numbers, currency etc.
+* looking up translations
+* interpolating data into translations
+* pluralizing translations
+* localizing dates, numbers, currency etc.
=== Looking up translations
@@ -351,14 +490,14 @@ I18n.t :message
I18n.t 'message'
-------------------------------------------------------
-translate also takes a :scope option which can contain one or many additional keys that will be used to specify a “namespace” or scope for a translation key:
++translate+ also takes a +:scope+ option which can contain one or many additional keys that will be used to specify a “namespace” or scope for a translation key:
[source, ruby]
-------------------------------------------------------
I18n.t :invalid, :scope => [:active_record, :error_messages]
-------------------------------------------------------
-This looks up the :invalid message in the Active Record error messages.
+This looks up the +:invalid+ message in the Active Record error messages.
Additionally, both the key and scopes can be specified as dot separated keys as in:
@@ -389,7 +528,7 @@ I18n.t :missing, :default => 'Not here'
If the default value is a Symbol it will be used as a key and translated. One can provide multiple values as default. The first one that results in a value will be returned.
-E.g. the following first tries to translate the key :missing and then the key :also_missing. As both do not yield a result the string "Not here" will be returned:
+E.g. the following first tries to translate the key +:missing+ and then the key +:also_missing.+ As both do not yield a result the string "Not here" will be returned:
[source, ruby]
-------------------------------------------------------
@@ -417,9 +556,9 @@ I18n.t 'active_record.error_messages'
=== Interpolation
-In many cases you want to abstract your translations so that variables can be interpolated into the translation. For this reason the I18n API provides an interpolation feature.
+In many cases you want to abstract your translations so that *variables can be interpolated into the translation*. For this reason the I18n API provides an interpolation feature.
-All options besides :default and :scope that are passed to #translate will be interpolated to the translation:
+All options besides +:default+ and +:scope+ that are passed to +#translate+ will be interpolated to the translation:
[source, ruby]
-------------------------------------------------------
@@ -428,14 +567,14 @@ I18n.translate :thanks, :name => 'Jeremy'
# => 'Thanks Jeremy!'
-------------------------------------------------------
-If a translation uses :default or :scope as a interpolation variable an I18n::ReservedInterpolationKey exception is raised. If a translation expects an interpolation variable but it has not been passed to #translate an I18n::MissingInterpolationArgument exception is raised.
+If a translation uses +:default+ or +:scope+ as a interpolation variable an I+18n::ReservedInterpolationKey+ exception is raised. If a translation expects an interpolation variable but it has not been passed to +#translate+ an +I18n::MissingInterpolationArgument+ exception is raised.
=== Pluralization
In English there's only a singular and a plural form for a given string, e.g. "1 message" and "2 messages". Other languages (http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html#ar[Arabic], http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html#ja[Japanese], http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html#ru[Russian] and many more) have different grammars that have additional or less http://www.unicode.org/cldr/data/charts/supplemental/language_plural_rules.html[plural forms]. Thus, the I18n API provides a flexible pluralization feature.
-The :count interpolation variable has a special role in that it both is interpolated to the translation and used to pick a pluralization from the translations according to the pluralization rules defined by CLDR:
+The +:count+ interpolation variable has a special role in that it both is interpolated to the translation and used to pick a pluralization from the translations according to the pluralization rules defined by CLDR:
[source, ruby]
-------------------------------------------------------
@@ -447,22 +586,22 @@ I18n.translate :inbox, :count => 2
# => '2 messages'
-------------------------------------------------------
-The algorithm for pluralizations in :en is as simple as:
+The algorithm for pluralizations in +:en+ is as simple as:
[source, ruby]
-------------------------------------------------------
entry[count == 1 ? 0 : 1]
-------------------------------------------------------
-I.e. the translation denoted as :one is regarded as singular, the other is used as plural (including the count being zero).
+I.e. the translation denoted as +:one+ is regarded as singular, the other is used as plural (including the count being zero).
-If the lookup for the key does not return an Hash suitable for pluralization an I18n::InvalidPluralizationData exception is raised.
+If the lookup for the key does not return an Hash suitable for pluralization an +18n::InvalidPluralizationData+ exception is raised.
=== Setting and passing a locale
-The locale can be either set pseudo-globally to I18n.locale (which uses Thread.current like, e.g., Time.zone) or can be passed as an option to #translate and #localize.
+The locale can be either set pseudo-globally to +I18n.locale+ (which uses +Thread.current+ like, e.g., +Time.zone+) or can be passed as an option to +#translate+ and +#localize+.
-If no locale is passed I18n.locale is used:
+If no locale is passed +I18n.locale+ is used:
[source, ruby]
-------------------------------------------------------
@@ -479,7 +618,7 @@ I18n.t :foo, :locale => :de
I18n.l Time.now, :locale => :de
-------------------------------------------------------
-I18n.locale defaults to I18n.default_locale which defaults to :en. The default locale can be set like this:
++I18n.locale+ defaults to +I18n.default_locale+ which defaults to :+en+. The default locale can be set like this:
[source, ruby]
-------------------------------------------------------
@@ -512,9 +651,9 @@ pt:
bar: baz
-------------------------------------------------------
-As you see in both cases the toplevel key is the locale. :foo is a namespace key and :bar is the key for the translation "baz".
+As you see in both cases the toplevel key is the locale. +:foo+ is a namespace key and +:bar+ is the key for the translation "baz".
-Here is a "real" example from the ActiveSupport en.yml translations YAML file:
+Here is a "real" example from the ActiveSupport +en.yml+ translations YAML file:
[source, ruby]
-------------------------------------------------------
@@ -526,7 +665,7 @@ en:
long: "%B %d, %Y"
-------------------------------------------------------
-So, all of the following equivalent lookups will return the :short date format "%B %d":
+So, all of the following equivalent lookups will return the +:short+ date format +"%B %d"+:
[source, ruby]
-------------------------------------------------------
@@ -536,11 +675,11 @@ I18n.t :short, :scope => 'date.formats'
I18n.t :short, :scope => [:date, :formats]
-------------------------------------------------------
-Generally we recommend using YAML as a format for storing translations. There are cases though where you want to store Ruby lambdas as part of your locale data, e.g. for special date
+Generally we recommend using YAML as a format for storing translations. There are cases though where you want to store Ruby lambdas as part of your locale data, e.g. for special date.
=== Translations for Active Record models
-You can use the methods Model.human_name and Model.human_attribute_name(attribute) to transparently lookup translations for your model and attribute names.
+You can use the methods +Model.human_name+ and +Model.human_attribute_name(attribute)+ to transparently lookup translations for your model and attribute names.
For example when you add the following translations:
@@ -556,7 +695,7 @@ en:
# will translate User attribute "login" as "Handle"
-------------------------------------------------------
-Then User.human_name will return "Dude" and User.human_attribute_name(:login) will return "Handle".
+Then +User.human_name+ will return "Dude" and +User.human_attribute_name(:login)+ will return "Handle".
==== Error message scopes
@@ -564,7 +703,7 @@ Active Record validation error messages can also be translated easily. Active Re
This gives you quite powerful means to flexibly adjust your messages to your application's needs.
-Consider a User model with a validates_presence_of validation for the name attribute like this:
+Consider a User model with a +validates_presence_of+ validation for the name attribute like this:
[source, ruby]
-------------------------------------------------------
@@ -573,7 +712,7 @@ class User < ActiveRecord::Base
end
-------------------------------------------------------
-The key for the error message in this case is :blank. Active Record will lookup this key in the namespaces:
+The key for the error message in this case is +:blank+. Active Record will lookup this key in the namespaces:
[source, ruby]
-------------------------------------------------------
@@ -619,9 +758,9 @@ This way you can provide special translations for various error messages at diff
The translated model name, translated attribute name, and value are always available for interpolation.
-So, for example, instead of the default error message "can not be blank" you could use the attribute name like this: "Please fill in your {{attribute}}".
+So, for example, instead of the default error message +"can not be blank"+ you could use the attribute name like this:+ "Please fill in your {{attribute}}"+.
-count, where available, can be used for pluralization if present:
++count+, where available, can be used for pluralization if present:
|=====================================================================================================
| validation | with option | message | interpolation
@@ -651,7 +790,7 @@ count, where available, can be used for pluralization if present:
==== Translations for the Active Record error_messages_for helper
-If you are using the Active Record error_messages_for helper you will want to add translations for it.
+If you are using the Active Record +error_messages_for+ helper you will want to add translations for it.
Rails ships with the following translations:
@@ -674,23 +813,23 @@ Rails uses fixed strings and other localizations, such as format strings and oth
==== ActionView helper methods
-* distance_of_time_in_words translates and pluralizes its result and interpolates the number of seconds, minutes, hours and so on. See http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L51[datetime.distance_in_words] translations.
+* +distance_of_time_in_words+ translates and pluralizes its result and interpolates the number of seconds, minutes, hours and so on. See http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L51[datetime.distance_in_words] translations.
-* datetime_select and select_month use translated month names for populating the resulting select tag. See http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L15[date.month_names] for translations. datetime_select also looks up the order option from http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L18[date.order] (unless you pass the option explicitely). All date select helpers translate the prompt using the translations in the http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L83[datetime.prompts] scope if applicable.
+* +datetime_select+ and +select_month+ use translated month names for populating the resulting select tag. See http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L15[date.month_names] for translations. +datetime_select+ also looks up the order option from http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L18[date.order] (unless you pass the option explicitely). All date select helpers translate the prompt using the translations in the http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L83[datetime.prompts] scope if applicable.
-* The number_to_currency, number_with_precision, number_to_percentage, number_with_delimiter and humber_to_human_size helpers use the number format settings located in the http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L2[number] scope.
+* The +number_to_currency+, +number_with_precision+, +number_to_percentage+, +number_with_delimiter+ and +humber_to_human_size+ helpers use the number format settings located in the http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L2[number] scope.
==== Active Record methods
-* human_name and human_attribute_name use translations for model names and attribute names if available in the http://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml#L43[activerecord.models] scope. They also support translations for inherited class names (e.g. for use with STI) as explained above in "Error message scopes".
+* +human_name+ and +human_attribute_name+ use translations for model names and attribute names if available in the http://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml#L43[activerecord.models] scope. They also support translations for inherited class names (e.g. for use with STI) as explained above in "Error message scopes".
-* ActiveRecord::Errors#generate_message (which is used by Active Record validations but may also be used manually) uses human_name and human_attribute_name (see above). It also translates the error message and supports translations for inherited class names as explained above in "Error message scopes".
+* +ActiveRecord::Errors#generate_message+ (which is used by Active Record validations but may also be used manually) uses +human_name+ and +human_attribute_name+ (see above). It also translates the error message and supports translations for inherited class names as explained above in "Error message scopes".
-* ActiveRecord::Errors#full_messages prepends the attribute name to the error message using a separator that will be looked up from http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L91[activerecord.errors.format.separator] (and defaults to ' ').
+*+ ActiveRecord::Errors#full_messages+ prepends the attribute name to the error message using a separator that will be looked up from http://github.com/rails/rails/blob/master/actionpack/lib/action_view/locale/en.yml#L91[activerecord.errors.format.separator] (and defaults to +' '+).
==== ActiveSupport methods
-* Array#to_sentence uses format settings as given in the http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L30[support.array] scope.
+* +Array#to_sentence+ uses format settings as given in the http://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L30[support.array] scope.
== Customize your I18n setup
@@ -720,7 +859,7 @@ ReservedInterpolationKey # the translation contains a reserved interpolation
UnknownFileType # the backend does not know how to handle a file type that was added to I18n.load_path
-------------------------------------------------------
-The I18n API will catch all of these exceptions when they were thrown in the backend and pass them to the default_exception_handler method. This method will re-raise all exceptions except for MissingTranslationData exceptions. When a MissingTranslationData exception has been caught it will return the exception’s error message string containing the missing key/scope.
+The I18n API will catch all of these exceptions when they were thrown in the backend and pass them to the default_exception_handler method. This method will re-raise all exceptions except for +MissingTranslationData+ exceptions. When a +MissingTranslationData+ exception has been caught it will return the exception’s error message string containing the missing key/scope.
The reason for this is that during development you'd usually want your views to still render even though a translation is missing.
@@ -737,11 +876,11 @@ end
I18n.exception_handler = :just_raise_that_exception
-------------------------------------------------------
-This would re-raise all caught exceptions including MissingTranslationData.
+This would re-raise all caught exceptions including +MissingTranslationData+.
-Another example where the default behaviour is less desirable is the Rails TranslationHelper which provides the method #t (as well as #translate). When a MissingTranslationData exception occurs in this context the helper wraps the message into a span with the css class translation_missing.
+Another example where the default behaviour is less desirable is the Rails TranslationHelper which provides the method +#t+ (as well as +#translate+). When a +MissingTranslationData+ exception occurs in this context the helper wraps the message into a span with the CSS class +translation_missing+.
-To do so the helper forces I18n#translate to raise exceptions no matter what exception handler is defined by setting the :raise option:
+To do so the helper forces +I18n#translate+ to raise exceptions no matter what exception handler is defined by setting the +:raise+ option:
[source, ruby]
-------------------------------------------------------
@@ -762,13 +901,13 @@ I18n support in Ruby on Rails was introduced in the release 2.2 and is still evo
Thus we encourage everybody to experiment with new ideas and features in plugins or other libraries and make them available to the community. (Don't forget to announce your work on our http://groups.google.com/group/rails-i18n[mailinglist]!)
-If you find your own locale (language) missing from our http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale[example translations data] repository for Ruby on Rails
+If you find your own locale (language) missing from our http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale[example translations data] repository for Ruby on Rails, please http://github.com/guides/fork-a-project-and-submit-your-modifications[_fork_] the repository, add your data and send a http://github.com/guides/pull-requests[pull request].
== Resources
* http://rails-i18n.org[rails-i18n.org] - Homepage of the rails-i18n project. You can find lots of useful resources on the http://rails-i18n.org/wiki[wiki].
-* http://groups.google.com/group/rails-i18n[rails-i18n Google group] - The project's mailinglist.
+* http://groups.google.com/group/rails-i18n[rails-i18n Google group] - The project's mailing list.
* http://github.com/svenfuchs/rails-i18n/tree/master[Github: rails-i18n] - Code repository for the rails-i18n project. Most importantly you can find lots of http://github.com/svenfuchs/rails-i18n/tree/master/rails/locale[example translations] for Rails that should work for your application in most cases.
* http://i18n.lighthouseapp.com/projects/14948-rails-i18n/overview[Lighthouse: rails-i18n] - Issue tracker for the rails-i18n project.
* http://github.com/svenfuchs/i18n/tree/master[Github: i18n] - Code repository for the i18n gem.
@@ -777,8 +916,8 @@ If you find your own locale (language) missing from our http://github.com/svenfu
== Authors
-* Sven Fuchs[http://www.workingwithrails.com/person/9963-sven-fuchs] (initial author)
-* Karel Minarik[http://www.workingwithrails.com/person/7476-karel-mina-k]
+* http://www.workingwithrails.com/person/9963-sven-fuchs[Sven Fuchs] (initial author)
+* http://www.workingwithrails.com/person/7476-karel-mina-k[Karel Minařík]
If you found this guide useful please consider recommending its authors on http://www.workingwithrails.com[workingwithrails].
diff --git a/railties/doc/guides/source/index.txt b/railties/doc/guides/source/index.txt
index b32d8ef7b1..bb43b0175b 100644
--- a/railties/doc/guides/source/index.txt
+++ b/railties/doc/guides/source/index.txt
@@ -80,17 +80,17 @@ understand how to use routing in your own Rails applications, start here.
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.
***********************************************************
-.link:caching_with_rails.html[Rails Caching]
-***********************************************************
-CAUTION: link:http://rails.lighthouseapp.com/projects/16213/tickets/10[Lighthouse Ticket]
-
-This guide covers the three types of caching that Rails provides by default.
-***********************************************************
-
++++++++++++++++++++++++++++++++++++++
<h2>Digging Deeper</h2>
++++++++++++++++++++++++++++++++++++++
+.link:action_mailer_basics.html[Action Mailer Basics]
+***********************************************************
+CAUTION: link:http://rails.lighthouseapp.com/projects/16213/tickets/25[Lighthouse ticket]
+
+This guide describes how to use Action Mailer to send and receive emails.
+***********************************************************
+
.link:testing_rails_applications.html[Testing Rails Applications]
***********************************************************
CAUTION: link:http://rails.lighthouseapp.com/projects/16213/tickets/8[Lighthouse Ticket]
@@ -142,4 +142,4 @@ This guide covers the command line tools and rake tasks provided by Rails.
Authors who have contributed to complete guides are listed link:authors.html[here].
-This work is licensed under a link:http://creativecommons.org/licenses/by-nc-sa/3.0/[Creative Commons Attribution-Noncommercial-Share Alike 3.0 License]
+This work is licensed under a link:http://creativecommons.org/licenses/by-sa/3.0[Creative Commons Attribution-Share Alike 3.0 License]