Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge with docrails

  • Loading branch information...
commit dbbae5e00e49d3a69dc10978e38299e3f28dd1e1 1 parent 9eca588
@lifo lifo authored
Showing with 5,289 additions and 1,429 deletions.
  1. +21 −75 actionpack/README
  2. +17 −9 actionpack/lib/action_controller/caching/fragments.rb
  3. +12 −14 actionpack/lib/action_controller/caching/pages.rb
  4. +6 −1 actionpack/lib/action_controller/resources.rb
  5. +4 −2 actionpack/lib/action_controller/routing.rb
  6. +10 −0 actionpack/lib/action_controller/session/active_record_store.rb
  7. +6 −2 actionpack/lib/action_view/base.rb
  8. +1 −1  actionpack/lib/action_view/helpers/tag_helper.rb
  9. +2 −0  actionpack/lib/action_view/template_handlers/erb.rb
  10. +2 −0  activemodel/lib/active_model/errors.rb
  11. +42 −14 activerecord/lib/active_record/base.rb
  12. +2 −0  activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
  13. +9 −6 activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
  14. +3 −1 activerecord/lib/active_record/migration.rb
  15. +2 −0  activerecord/lib/active_record/schema_dumper.rb
  16. +9 −7 activerecord/lib/active_record/validations.rb
  17. +2 −0  activeresource/lib/active_resource/base.rb
  18. +2 −0  activesupport/lib/active_support/buffered_logger.rb
  19. +2 −0  activesupport/lib/active_support/core_ext/logger.rb
  20. +1 −1  activesupport/lib/active_support/inflector.rb
  21. +2 −1  railties/Rakefile
  22. +26 −0 railties/doc/guides/asciidoc.conf
  23. +9 −4 railties/doc/guides/html/2_2_release_notes.html
  24. +10 −10 railties/doc/guides/html/actioncontroller_basics.html
  25. +451 −3 railties/doc/guides/html/activerecord_validations_callbacks.html
  26. +12 −9 railties/doc/guides/html/association_basics.html
  27. +5 −0 railties/doc/guides/html/authors.html
  28. +104 −20 railties/doc/guides/html/caching_with_rails.html
  29. +125 −2 railties/doc/guides/html/command_line.html
  30. +155 −147 railties/doc/guides/html/configuring.html
  31. +815 −497 railties/doc/guides/html/creating_plugins.html
  32. +65 −27 railties/doc/guides/html/finders.html
  33. +25 −8 railties/doc/guides/html/getting_started_with_rails.html
  34. +1,086 −0 railties/doc/guides/html/i18n.html
  35. +13 −0 railties/doc/guides/html/index.html
  36. +2 −1  railties/doc/guides/html/migrations.html
  37. +4 −4 railties/doc/guides/html/routing_outside_in.html
  38. +5 −4 railties/doc/guides/source/2_2_release_notes.txt
  39. +1 −1  railties/doc/guides/source/actioncontroller_basics/cookies.txt
  40. +2 −2 railties/doc/guides/source/actioncontroller_basics/filters.txt
  41. +2 −2 railties/doc/guides/source/actioncontroller_basics/parameter_filtering.txt
  42. +3 −3 railties/doc/guides/source/actioncontroller_basics/request_response_objects.txt
  43. +1 −1  railties/doc/guides/source/actioncontroller_basics/streaming.txt
  44. +1 −1  railties/doc/guides/source/actioncontroller_basics/verification.txt
  45. +284 −4 railties/doc/guides/source/activerecord_validations_callbacks.txt
  46. +15 −9 railties/doc/guides/source/association_basics.txt
  47. +6 −0 railties/doc/guides/source/authors.txt
  48. +99 −20 railties/doc/guides/source/caching_with_rails.txt
  49. +108 −2 railties/doc/guides/source/command_line.txt
  50. +127 −158 railties/doc/guides/source/configuring.txt
  51. +1 −1  railties/doc/guides/source/creating_plugins/acts_as_yaffle.txt
  52. +88 −30 railties/doc/guides/source/creating_plugins/appendix.txt
  53. +6 −2 railties/doc/guides/source/creating_plugins/controllers.txt
  54. +4 −29 railties/doc/guides/source/creating_plugins/core_ext.txt
  55. +50 −0 railties/doc/guides/source/creating_plugins/gems.txt
  56. +144 −0 railties/doc/guides/source/creating_plugins/generator_commands.txt
  57. +98 −0 railties/doc/guides/source/creating_plugins/generators.txt
  58. +1 −3 railties/doc/guides/source/creating_plugins/helpers.txt
  59. +15 −7 railties/doc/guides/source/creating_plugins/index.txt
  60. +0 −156 railties/doc/guides/source/creating_plugins/migration_generator.txt
  61. +213 −0 railties/doc/guides/source/creating_plugins/migrations.txt
  62. +4 −6 railties/doc/guides/source/creating_plugins/models.txt
  63. +0 −69 railties/doc/guides/source/creating_plugins/odds_and_ends.txt
  64. +18 −0 railties/doc/guides/source/creating_plugins/rdoc.txt
  65. +11 −11 railties/doc/guides/source/creating_plugins/{custom_route.txt → routes.txt}
  66. +84 −0 railties/doc/guides/source/creating_plugins/setup.txt
  67. +27 −0 railties/doc/guides/source/creating_plugins/tasks.txt
  68. +165 −0 railties/doc/guides/source/creating_plugins/tests.txt
  69. +51 −25 railties/doc/guides/source/finders.txt
  70. +24 −8 railties/doc/guides/source/getting_started_with_rails.txt
  71. +542 −0 railties/doc/guides/source/i18n.txt
  72. +10 −0 railties/doc/guides/source/index.txt
  73. +1 −1  railties/doc/guides/source/migrations/index.txt
  74. +2 −0  railties/doc/guides/source/migrations/rakeing_around.txt
  75. +4 −4 railties/doc/guides/source/routing_outside_in.txt
  76. +4 −0 railties/doc/guides/source/stylesheets/base.css
  77. +3 −3 railties/doc/guides/source/testing_rails_applications.txt
  78. +1 −1  railties/lib/tasks/databases.rake
View
96 actionpack/README
@@ -10,7 +10,7 @@ Action Pack implements these actions as public methods on Action Controllers
and uses Action Views to implement the template rendering. Action Controllers
are then responsible for handling all the actions relating to a certain part
of an application. This grouping usually consists of actions for lists and for
-CRUDs revolving around a single (or a few) model objects. So ContactController
+CRUDs revolving around a single (or a few) model objects. So ContactsController
would be responsible for listing contacts, creating, deleting, and updating
contacts. A WeblogController could be responsible for both posts and comments.
@@ -33,7 +33,7 @@ A short rundown of the major features:
* Actions grouped in controller as methods instead of separate command objects
and can therefore share helper methods
- BlogController < ActionController::Base
+ CustomersController < ActionController::Base
def show
@customer = find_customer
end
@@ -42,7 +42,7 @@ A short rundown of the major features:
@customer = find_customer
@customer.attributes = params[:customer]
@customer.save ?
- redirect_to(:action => "display") :
+ redirect_to(:action => "show") :
render(:action => "edit")
end
@@ -59,7 +59,7 @@ A short rundown of the major features:
Title: <%= post.title %>
<% end %>
- All post titles: <%= @post.collect{ |p| p.title }.join ", " %>
+ All post titles: <%= @posts.collect{ |p| p.title }.join ", " %>
<% unless @person.is_client? %>
Not for clients to see...
@@ -123,7 +123,7 @@ A short rundown of the major features:
<%= text_field "post", "title", "size" => 30 %>
<%= html_date_select(Date.today) %>
<%= link_to "New post", :controller => "post", :action => "new" %>
- <%= truncate(post.title, 25) %>
+ <%= truncate(post.title, :length => 25) %>
{Learn more}[link:classes/ActionView/Helpers.html]
@@ -177,21 +177,6 @@ A short rundown of the major features:
{Learn more}[link:classes/ActionView/Helpers/JavaScriptHelper.html]
-* Pagination for navigating lists of results
-
- # controller
- def list
- @pages, @people =
- paginate :people, :order => 'last_name, first_name'
- end
-
- # view
- <%= link_to "Previous page", { :page => @pages.current.previous } if @pages.current.previous %>
- <%= link_to "Next page", { :page => @pages.current.next } if @pages.current.next %>
-
- {Learn more}[link:classes/ActionController/Pagination.html]
-
-
* Easy testing of both controller and rendered template through ActionController::TestCase
class LoginControllerTest < ActionController::TestCase
@@ -215,11 +200,11 @@ A short rundown of the major features:
If Active Record is used as the model, you'll have the database debugging
as well:
- Processing WeblogController#create (for 127.0.0.1 at Sat Jun 19 14:04:23)
- Params: {"controller"=>"weblog", "action"=>"create",
+ Processing PostsController#create (for 127.0.0.1 at Sat Jun 19 14:04:23)
+ Params: {"controller"=>"posts", "action"=>"create",
"post"=>{"title"=>"this is good"} }
SQL (0.000627) INSERT INTO posts (title) VALUES('this is good')
- Redirected to http://test/weblog/display/5
+ Redirected to http://example.com/posts/5
Completed in 0.221764 (4 reqs/sec) | DB: 0.059920 (27%)
You specify a logger through a class method, such as:
@@ -256,30 +241,6 @@ A short rundown of the major features:
{Learn more}[link:classes/ActionController/Caching.html]
-* Component requests from one controller to another
-
- class WeblogController < ActionController::Base
- # Performs a method and then lets hello_world output its render
- def delegate_action
- do_other_stuff_before_hello_world
- render_component :controller => "greeter", :action => "hello_world"
- end
- end
-
- class GreeterController < ActionController::Base
- def hello_world
- render_text "Hello World!"
- end
- end
-
- The same can be done in a view to do a partial rendering:
-
- Let's see a greeting:
- <%= render_component :controller => "greeter", :action => "hello_world" %>
-
- {Learn more}[link:classes/ActionController/Components.html]
-
-
* Powerful debugging mechanism for local requests
All exceptions raised on actions performed on the request of a local user
@@ -336,7 +297,7 @@ A short rundown of the major features:
class WeblogController < ActionController::Base
def create
post = Post.create(params[:post])
- redirect_to :action => "display", :id => post.id
+ redirect_to :action => "show", :id => post.id
end
end
@@ -362,7 +323,7 @@ methods:
@posts = Post.find(:all)
end
- def display
+ def show
@post = Post.find(params[:id])
end
@@ -372,7 +333,7 @@ methods:
def create
@post = Post.create(params[:post])
- redirect_to :action => "display", :id => @post.id
+ redirect_to :action => "show", :id => @post.id
end
end
@@ -385,47 +346,32 @@ request from the web-server (like to be Apache).
And the templates look like this:
- weblog/layout.erb:
+ weblog/layout.html.erb:
<html><body>
<%= yield %>
</body></html>
- weblog/index.erb:
+ weblog/index.html.erb:
<% for post in @posts %>
- <p><%= link_to(post.title, :action => "display", :id => post.id %></p>
+ <p><%= link_to(post.title, :action => "show", :id => post.id) %></p>
<% end %>
- weblog/display.erb:
+ weblog/show.html.erb:
<p>
- <b><%= post.title %></b><br/>
- <b><%= post.content %></b>
+ <b><%= @post.title %></b><br/>
+ <b><%= @post.content %></b>
</p>
- weblog/new.erb:
+ weblog/new.html.erb:
<%= form "post" %>
This simple setup will list all the posts in the system on the index page,
which is called by accessing /weblog/. It uses the form builder for the Active
Record model to make the new screen, which in turn hands everything over to
the create action (that's the default target for the form builder when given a
-new model). After creating the post, it'll redirect to the display page using
-an URL such as /weblog/display/5 (where 5 is the id of the post).
-
-
-== Examples
-
-Action Pack ships with three examples that all demonstrate an increasingly
-detailed view of the possibilities. First is blog_controller that is just a
-single file for the whole MVC (but still split into separate parts). Second is
-the debate_controller that uses separate template files and multiple screens.
-Third is the address_book_controller that uses the layout feature to separate
-template casing from content.
-
-Please note that you might need to change the "shebang" line to
-#!/usr/local/env ruby, if your Ruby is not placed in /usr/local/bin/ruby
+new model). After creating the post, it'll redirect to the show page using
+an URL such as /weblog/5 (where 5 is the id of the post).
-Also note that these examples are all for demonstrating using Action Pack on
-its own. Not for when it's used inside of Rails.
== Download
@@ -460,4 +406,4 @@ And as Jim from Rake says:
Feel free to submit commits or feature requests. If you send a patch,
remember to update the corresponding unit tests. If fact, I prefer
- new feature to be submitted in the form of new unit tests.
+ new feature to be submitted in the form of new unit tests.
View
26 actionpack/lib/action_controller/caching/fragments.rb
@@ -83,15 +83,23 @@ def fragment_exist?(key, options = nil)
end
end
- # Name can take one of three forms:
- # * String: This would normally take the form of a path like "pages/45/notes"
- # * Hash: Is treated as an implicit call to url_for, like { :controller => "pages", :action => "notes", :id => 45 }
- # * Regexp: Will destroy all the matched fragments, example:
- # %r{pages/\d*/notes}
- # Ensure you do not specify start and finish in the regex (^$) because
- # the actual filename matched looks like ./cache/filename/path.cache
- # Regexp expiration is only supported on caches that can iterate over
- # all keys (unlike memcached).
+ # Removes fragments from the cache.
+ #
+ # +key+ can take one of three forms:
+ # * String - This would normally take the form of a path, like
+ # <tt>"pages/45/notes"</tt>.
+ # * Hash - Treated as an implicit call to +url_for+, like
+ # <tt>{:controller => "pages", :action => "notes", :id => 45}</tt>
+ # * Regexp - Will remove any fragment that matches, so
+ # <tt>%r{pages/\d*/notes}</tt> might remove all notes. Make sure you
+ # don't use anchors in the regex (<tt>^</tt> or <tt>$</tt>) because
+ # the actual filename matched looks like
+ # <tt>./cache/filename/path.cache</tt>. Note: Regexp expiration is
+ # only supported on caches that can iterate over all keys (unlike
+ # memcached).
+ #
+ # +options+ is passed through to the cache store's <tt>delete</tt>
+ # method (or <tt>delete_matched</tt>, for Regexp keys.)
def expire_fragment(key, options = nil)
return unless cache_configured?
View
26 actionpack/lib/action_controller/caching/pages.rb
@@ -33,28 +33,26 @@ module Caching
#
# Additionally, you can expire caches using Sweepers that act on changes in the model to determine when a cache is supposed to be
# expired.
- #
- # == Setting the cache directory
- #
- # The cache directory should be the document root for the web server and is set using <tt>Base.page_cache_directory = "/document/root"</tt>.
- # For Rails, this directory has already been set to Rails.public_path (which is usually set to <tt>RAILS_ROOT + "/public"</tt>). Changing
- # this setting can be useful to avoid naming conflicts with files in <tt>public/</tt>, but doing so will likely require configuring your
- # web server to look in the new location for cached files.
- #
- # == Setting the cache extension
- #
- # Most Rails requests do not have an extension, such as <tt>/weblog/new</tt>. In these cases, the page caching mechanism will add one in
- # order to make it easy for the cached files to be picked up properly by the web server. By default, this cache extension is <tt>.html</tt>.
- # If you want something else, like <tt>.php</tt> or <tt>.shtml</tt>, just set Base.page_cache_extension. In cases where a request already has an
- # extension, such as <tt>.xml</tt> or <tt>.rss</tt>, page caching will not add an extension. This allows it to work well with RESTful apps.
module Pages
def self.included(base) #:nodoc:
base.extend(ClassMethods)
base.class_eval do
@@page_cache_directory = defined?(Rails.public_path) ? Rails.public_path : ""
+ ##
+ # :singleton-method:
+ # The cache directory should be the document root for the web server and is set using <tt>Base.page_cache_directory = "/document/root"</tt>.
+ # For Rails, this directory has already been set to Rails.public_path (which is usually set to <tt>RAILS_ROOT + "/public"</tt>). Changing
+ # this setting can be useful to avoid naming conflicts with files in <tt>public/</tt>, but doing so will likely require configuring your
+ # web server to look in the new location for cached files.
cattr_accessor :page_cache_directory
@@page_cache_extension = '.html'
+ ##
+ # :singleton-method:
+ # Most Rails requests do not have an extension, such as <tt>/weblog/new</tt>. In these cases, the page caching mechanism will add one in
+ # order to make it easy for the cached files to be picked up properly by the web server. By default, this cache extension is <tt>.html</tt>.
+ # If you want something else, like <tt>.php</tt> or <tt>.shtml</tt>, just set Base.page_cache_extension. In cases where a request already has an
+ # extension, such as <tt>.xml</tt> or <tt>.rss</tt>, page caching will not add an extension. This allows it to work well with RESTful apps.
cattr_accessor :page_cache_extension
end
end
View
7 actionpack/lib/action_controller/resources.rb
@@ -283,7 +283,12 @@ def initialize(entity, options)
# * <tt>:new</tt> - Same as <tt>:collection</tt>, but for actions that operate on the new \resource action.
# * <tt>:controller</tt> - Specify the controller name for the routes.
# * <tt>:singular</tt> - Specify the singular name used in the member routes.
- # * <tt>:requirements</tt> - Set custom routing parameter requirements.
+ # * <tt>:requirements</tt> - Set custom routing parameter requirements; this is a hash of either
+ # regular expressions (which must match for the route to match) or extra parameters. For example:
+ #
+ # map.resource :profile, :path_prefix => ':name', :requirements => { :name => /[a-zA-Z]+/, :extra => 'value' }
+ #
+ # will only match if the first part is alphabetic, and will pass the parameter :extra to the controller.
# * <tt>:conditions</tt> - Specify custom routing recognition conditions. \Resources sets the <tt>:method</tt> value for the method-specific routes.
# * <tt>:as</tt> - Specify a different \resource name to use in the URL path. For example:
# # products_path == '/productos'
View
6 actionpack/lib/action_controller/routing.rb
@@ -83,9 +83,11 @@ module ActionController
# This sets up +blog+ as the default controller if no other is specified.
# This means visiting '/' would invoke the blog controller.
#
- # More formally, you can define defaults in a route with the <tt>:defaults</tt> key.
+ # More formally, you can include arbitrary parameters in the route, thus:
#
- # map.connect ':controller/:action/:id', :action => 'show', :defaults => { :page => 'Dashboard' }
+ # map.connect ':controller/:action/:id', :action => 'show', :page => 'Dashboard'
+ #
+ # This will pass the :page parameter to all incoming requests that match this route.
#
# Note: The default routes, as provided by the Rails generator, make all actions in every
# controller accessible via GET requests. You should consider removing them or commenting
View
10 actionpack/lib/action_controller/session/active_record_store.rb
@@ -56,6 +56,8 @@ def model
class ActiveRecordStore
# The default Active Record class.
class Session < ActiveRecord::Base
+ ##
+ # :singleton-method:
# Customizable data column name. Defaults to 'data'.
cattr_accessor :data_column_name
self.data_column_name = 'data'
@@ -166,17 +168,25 @@ def raise_on_session_data_overflow!
# binary session data in a +text+ column. For higher performance,
# store in a +blob+ column instead and forgo the Base64 encoding.
class SqlBypass
+ ##
+ # :singleton-method:
# Use the ActiveRecord::Base.connection by default.
cattr_accessor :connection
+ ##
+ # :singleton-method:
# The table name defaults to 'sessions'.
cattr_accessor :table_name
@@table_name = 'sessions'
+ ##
+ # :singleton-method:
# The session id field defaults to 'session_id'.
cattr_accessor :session_id_column
@@session_id_column = 'session_id'
+ ##
+ # :singleton-method:
# The data field defaults to 'data'.
cattr_accessor :data_column
@@data_column = 'data'
View
8 actionpack/lib/action_view/base.rb
@@ -183,13 +183,17 @@ def self.exempt_from_layout(*extensions)
@@exempt_from_layout.merge(regexps)
end
+ @@debug_rjs = false
+ ##
+ # :singleton-method:
# Specify whether RJS responses should be wrapped in a try/catch block
# that alert()s the caught exception (and then re-raises it).
- @@debug_rjs = false
cattr_accessor :debug_rjs
- # A warning will be displayed whenever an action results in a cache miss on your view paths.
@@warn_cache_misses = false
+ ##
+ # :singleton-method:
+ # A warning will be displayed whenever an action results in a cache miss on your view paths.
cattr_accessor :warn_cache_misses
attr_internal :request
View
2  actionpack/lib/action_view/helpers/tag_helper.rb
@@ -97,7 +97,7 @@ def cdata_section(content)
# Returns an escaped version of +html+ without affecting existing escaped entities.
#
# ==== Examples
- # escape_once("1 > 2 &amp; 3")
+ # escape_once("1 < 2 &amp; 3")
# # => "1 &lt; 2 &amp; 3"
#
# escape_once("&lt;&lt; Accept & Checkout")
View
2  actionpack/lib/action_view/template_handlers/erb.rb
@@ -3,6 +3,8 @@ module TemplateHandlers
class ERB < TemplateHandler
include Compilable
+ ##
+ # :singleton-method:
# Specify trim mode for the ERB compiler. Defaults to '-'.
# See ERb documentation for suitable values.
cattr_accessor :erb_trim_mode
View
2  activemodel/lib/active_model/errors.rb
@@ -24,6 +24,8 @@ class Errors < Hash
:even => "must be even"
}
+ ##
+ # :singleton-method:
# Holds a hash with all the default error messages that can be replaced by your own copy or localizations.
cattr_accessor :default_error_messages
View
56 activerecord/lib/active_record/base.rb
@@ -389,6 +389,8 @@ def initialize(errors)
# So it's possible to assign a logger to the class through <tt>Base.logger=</tt> which will then be used by all
# instances in the current object space.
class Base
+ ##
+ # :singleton-method:
# Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed
# on to any new database connections made and which can be retrieved on both a class and instance level by calling +logger+.
cattr_accessor :logger, :instance_writer => false
@@ -414,7 +416,9 @@ def self.reset_subclasses #:nodoc:
end
@@subclasses = {}
-
+
+ ##
+ # :singleton-method:
# Contains the database configuration - as is typically stored in config/database.yml -
# as a Hash.
#
@@ -443,6 +447,8 @@ def self.reset_subclasses #:nodoc:
cattr_accessor :configurations, :instance_writer => false
@@configurations = {}
+ ##
+ # :singleton-method:
# Accessor for the prefix type that will be prepended to every primary key column name. The options are :table_name and
# :table_name_with_underscore. If the first is specified, the Product class will look for "productid" instead of "id" as
# the primary column. If the latter is specified, the Product class will look for "product_id" instead of "id". Remember
@@ -450,34 +456,46 @@ def self.reset_subclasses #:nodoc:
cattr_accessor :primary_key_prefix_type, :instance_writer => false
@@primary_key_prefix_type = nil
+ ##
+ # :singleton-method:
# Accessor for the name of the prefix string to prepend to every table name. So if set to "basecamp_", all
# table names will be named like "basecamp_projects", "basecamp_people", etc. This is a convenient way of creating a namespace
# for tables in a shared database. By default, the prefix is the empty string.
cattr_accessor :table_name_prefix, :instance_writer => false
@@table_name_prefix = ""
+ ##
+ # :singleton-method:
# Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
# "people_basecamp"). By default, the suffix is the empty string.
cattr_accessor :table_name_suffix, :instance_writer => false
@@table_name_suffix = ""
+ ##
+ # :singleton-method:
# Indicates whether table names should be the pluralized versions of the corresponding class names.
# If true, the default table name for a Product class will be +products+. If false, it would just be +product+.
# See table_name for the full rules on table/class naming. This is true, by default.
cattr_accessor :pluralize_table_names, :instance_writer => false
@@pluralize_table_names = true
+ ##
+ # :singleton-method:
# Determines whether to use ANSI codes to colorize the logging statements committed by the connection adapter. These colors
# make it much easier to overview things during debugging (when used through a reader like +tail+ and on a black background), but
# may complicate matters if you use software like syslog. This is true, by default.
cattr_accessor :colorize_logging, :instance_writer => false
@@colorize_logging = true
+ ##
+ # :singleton-method:
# Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling dates and times from the database.
# This is set to :local by default.
cattr_accessor :default_timezone, :instance_writer => false
@@default_timezone = :local
+ ##
+ # :singleton-method:
# Specifies the format to use when dumping the database schema with Rails'
# Rakefile. If :sql, the schema is dumped as (potentially database-
# specific) SQL statements. If :ruby, the schema is dumped as an
@@ -487,6 +505,8 @@ def self.reset_subclasses #:nodoc:
cattr_accessor :schema_format , :instance_writer => false
@@schema_format = :ruby
+ ##
+ # :singleton-method:
# Specify whether or not to use timestamps for migration numbers
cattr_accessor :timestamped_migrations , :instance_writer => false
@@timestamped_migrations = true
@@ -640,16 +660,24 @@ def find_by_sql(sql)
connection.select_all(sanitize_sql(sql), "#{name} Load").collect! { |record| instantiate(record) }
end
- # Checks whether a record exists in the database that matches conditions given. These conditions
- # can either be a single integer representing a primary key id to be found, or a condition to be
- # matched like using ActiveRecord#find.
+
+ # Returns true if a record exists in the table that matches the +id+ or
+ # conditions given, or false otherwise. The argument can take four forms:
+ #
+ # * Integer - Finds the record with this primary key.
+ # * String - Finds the record with a primary key corresponding to this
+ # string (such as <tt>'5'</tt>).
+ # * Array - Finds the record that matches these +find+-style conditions
+ # (such as <tt>['color = ?', 'red']</tt>).
+ # * Hash - Finds the record that matches these +find+-style conditions
+ # (such as <tt>{:color => 'red'}</tt>).
#
- # The +id_or_conditions+ parameter can be an Integer or a String if you want to search the primary key
- # column of the table for a matching id, or if you're looking to match against a condition you can use
- # an Array or a Hash.
+ # For more information about specifying conditions as a Hash or Array,
+ # see the Conditions section in the introduction to ActiveRecord::Base.
#
- # Possible gotcha: You can't pass in a condition as a string e.g. "name = 'Jamie'", this would be
- # sanitized and then queried against the primary key column as "id = 'name = \'Jamie"
+ # Note: You can't pass in a condition as a string (like <tt>name =
+ # 'Jamie'</tt>), since it would be sanitized and then queried against
+ # the primary key column, like <tt>id = 'name = \'Jamie\''</tt>.
#
# ==== Examples
# Person.exists?(5)
@@ -2320,15 +2348,15 @@ def id
# object. The default implementation returns this record's id as a String,
# or nil if this record's unsaved.
#
- # For example, suppose that you have a Users model, and that you have a
- # <tt>map.resources :users</tt> route. Normally, +users_path+ will
- # construct an URI with the user object's 'id' in it:
+ # For example, suppose that you have a User model, and that you have a
+ # <tt>map.resources :users</tt> route. Normally, +user_path+ will
+ # construct a path with the user object's 'id' in it:
#
# user = User.find_by_name('Phusion')
# user_path(user) # => "/users/1"
#
- # You can override +to_param+ in your model to make +users_path+ construct
- # an URI using the user's name instead of the user's id:
+ # You can override +to_param+ in your model to make +user_path+ construct
+ # a path using the user's name instead of the user's id:
#
# class User < ActiveRecord::Base
# def to_param # overridden
View
2  activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
@@ -7,6 +7,8 @@ def initialize (config, adapter_method)
end
end
+ ##
+ # :singleton-method:
# The connection handler
cattr_accessor :connection_handler, :instance_writer => false
@@connection_handler = ConnectionAdapters::ConnectionHandler.new
View
15 activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -156,13 +156,16 @@ def missing_default_forged_as_empty_string?(default)
# * <tt>:sslcapath</tt> - Necessary to use MySQL with an SSL connection.
# * <tt>:sslcipher</tt> - Necessary to use MySQL with an SSL connection.
#
- # By default, the MysqlAdapter will consider all columns of type <tt>tinyint(1)</tt>
- # as boolean. If you wish to disable this emulation (which was the default
- # behavior in versions 0.13.1 and earlier) you can add the following line
- # to your environment.rb file:
- #
- # ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false
class MysqlAdapter < AbstractAdapter
+
+ ##
+ # :singleton-method:
+ # By default, the MysqlAdapter will consider all columns of type <tt>tinyint(1)</tt>
+ # as boolean. If you wish to disable this emulation (which was the default
+ # behavior in versions 0.13.1 and earlier) you can add the following line
+ # to your environment.rb file:
+ #
+ # ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false
cattr_accessor :emulate_booleans
self.emulate_booleans = true
View
4 activerecord/lib/active_record/migration.rb
@@ -130,7 +130,9 @@ def initialize(name)
# To run migrations against the currently configured database, use
# <tt>rake db:migrate</tt>. This will update the database by running all of the
# pending migrations, creating the <tt>schema_migrations</tt> table
- # (see "About the schema_migrations table" section below) if missing.
+ # (see "About the schema_migrations table" section below) if missing. It will also
+ # invoke the db:schema:dump task, which will update your db/schema.rb file
+ # to match the structure of your database.
#
# To roll the database back to a previous migration version, use
# <tt>rake db:migrate VERSION=X</tt> where <tt>X</tt> is the version to which
View
2  activerecord/lib/active_record/schema_dumper.rb
@@ -7,6 +7,8 @@ module ActiveRecord
class SchemaDumper #:nodoc:
private_class_method :new
+ ##
+ # :singleton-method:
# A list of tables which should not be dumped to the schema.
# Acceptable values are strings as well as regexp.
# This setting is only used if ActiveRecord::Base.schema_format == :ruby
View
16 activerecord/lib/active_record/validations.rb
@@ -494,18 +494,20 @@ def validates_acceptance_of(*attr_names)
# The first_name attribute must be in the object and it cannot be blank.
#
# If you want to validate the presence of a boolean field (where the real values are true and false),
- # you will want to use validates_inclusion_of :field_name, :in => [true, false]
- # This is due to the way Object#blank? handles boolean values. false.blank? # => true
+ # you will want to use <tt>validates_inclusion_of :field_name, :in => [true, false]</tt>.
+ #
+ # This is due to the way Object#blank? handles boolean values: <tt>false.blank? # => true</tt>.
#
# Configuration options:
# * <tt>message</tt> - A custom error message (default is: "can't be blank").
- # * <tt>on</tt> - Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, <tt>:update</tt>).
+ # * <tt>on</tt> - Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>,
+ # <tt>:update</tt>).
# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should
- # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The
- # method, proc or string should return or evaluate to a true or false value.
+ # occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>).
+ # The method, proc or string should return or evaluate to a true or false value.
# * <tt>unless</tt> - Specifies a method, proc or string to call to determine if the validation should
- # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The
- # method, proc or string should return or evaluate to a true or false value.
+ # not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>).
+ # The method, proc or string should return or evaluate to a true or false value.
#
def validates_presence_of(*attr_names)
configuration = { :on => :save }
View
2  activeresource/lib/active_resource/base.rb
@@ -202,6 +202,8 @@ module ActiveResource
# sets the <tt>read_timeout</tt> of the internal Net::HTTP instance to the same value. The default
# <tt>read_timeout</tt> is 60 seconds on most Ruby implementations.
class Base
+ ##
+ # :singleton-method:
# The logger for diagnosing and tracing Active Resource calls.
cattr_accessor :logger
View
2  activesupport/lib/active_support/buffered_logger.rb
@@ -13,6 +13,8 @@ module Severity
MAX_BUFFER_SIZE = 1000
+ ##
+ # :singleton-method:
# Set to false to disable the silencer
cattr_accessor :silencer
self.silencer = true
View
2  activesupport/lib/active_support/core_ext/logger.rb
@@ -30,6 +30,8 @@ def around_#{level}(before_message, after_message, &block)
#
# Note: This logger is deprecated in favor of ActiveSupport::BufferedLogger
class Logger
+ ##
+ # :singleton-method:
# Set to false to disable the silencer
cattr_accessor :silencer
self.silencer = true
View
2  activesupport/lib/active_support/inflector.rb
@@ -254,7 +254,7 @@ def demodulize(class_name_in_module)
# @person = Person.find(1)
# # => #<Person id: 1, name: "Donald E. Knuth">
#
- # <%= link_to(@person.name, person_path %>
+ # <%= link_to(@person.name, person_path(@person)) %>
# # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
def parameterize(string, sep = '-')
re_sep = Regexp.escape(sep)
View
3  railties/Rakefile
@@ -282,6 +282,7 @@ task :guides do
FileUtils.mkdir(html)
template = File.expand_path("doc/guides/source/templates/guides.html.erb")
+ asciidoc_conf = 'doc/guides/asciidoc.conf'
ignore = ['..', 'icons', 'images', 'templates', 'stylesheets']
ignore << 'active_record_basics.txt'
@@ -311,7 +312,7 @@ task :guides do
begin
puts "GENERATING => #{output}"
ENV['MANUALSONRAILS_TOC'] = 'no' if indexless.include?(entry)
- Mizuho::Generator.new(input, :output => output, :template => template).start
+ Mizuho::Generator.new(input, :output => output, :template => template, :conf_file => asciidoc_conf).start
rescue Mizuho::GenerationError
STDERR.puts "*** ERROR"
exit 2
View
26 railties/doc/guides/asciidoc.conf
@@ -0,0 +1,26 @@
+# Asciidoc substitutes some characters by default, those are called
+# "replacements" in the docs. For example => becomes a unicode arrow.
+#
+# We override replacements to allow copy & paste of source code.
+
+[replacements]
+
+# Ellipsis
+(?<!\\)\.\.\.=...
+\\\.\.\.=...
+
+# -> right arrow
+(?<!\\)-&gt;==-&gt;
+\\-&gt;=-&gt;
+
+# => right double arrow
+(?<!\\)\=&gt;==&gt;
+\\\=&gt;==&gt;
+
+# <- left arrow
+(?<!\\)&lt;-=&lt;-
+\\&lt;-=&lt;-
+
+# <= left double arrow
+(?<!\\)&lt;\==&lt;=
+\\&lt;\==&lt;=
View
13 railties/doc/guides/html/2_2_release_notes.html
@@ -789,7 +789,7 @@ <h3 id="_other_action_controller_changes">6.4. Other Action Controller Changes</
</li>
<li>
<p>
-The HTTP Accept header is disabled by default now. You should prefer the use of formatted URLs (such as <tt>/customers/1.xml</tt>) to indicate the format that you want. If you need the Accept headers, you can turn them back on with <tt>config.action_controller.user_accept_header = true</tt>.
+The HTTP Accept header is disabled by default now. You should prefer the use of formatted URLs (such as <tt>/customers/1.xml</tt>) to indicate the format that you want. If you need the Accept headers, you can turn them back on with <tt>config.action_controller.use_accept_header = true</tt>.
</p>
</li>
<li>
@@ -974,7 +974,7 @@ <h3 id="_other_active_support_changes">9.4. Other Active Support Changes</h3>
</li>
<li>
<p>
-<tt>Array#second</tt> through <tt>Array#tenth</tt> as aliases for <tt>Array#[1]</tt> through <tt>Array#[9]</tt>
+<tt>Array#second</tt> through <tt>Array#fifth</tt> as aliases for <tt>Array#[1]</tt> through <tt>Array#[4]</tt>
</p>
</li>
<li>
@@ -994,7 +994,7 @@ <h3 id="_other_active_support_changes">9.4. Other Active Support Changes</h3>
</li>
<li>
<p>
-The included TzInfo library has been upgraded to version 0.3.11.
+The included TzInfo library has been upgraded to version 0.3.12.
</p>
</li>
<li>
@@ -1017,7 +1017,7 @@ <h3 id="_tt_config_gems_tt">10.1. <tt>config.gems</tt></h3>
</li>
<li>
<p>
-<tt>rake gems</tt> to list all configured gems, as well as whether they (and their dependencies) are installed or frozen
+<tt>rake gems</tt> to list all configured gems, as well as whether they (and their dependencies) are installed, frozen, or framework (framework gems are those loaded by Rails before the gem dependency code is executed; such gems cannot be frozen)
</p>
</li>
<li>
@@ -1068,6 +1068,11 @@ <h3 id="_tt_config_gems_tt">10.1. <tt>config.gems</tt></h3>
<a href="http://afreshcup.com/2008/10/25/rails-212-and-22rc1-update-your-rubygems/">Rails 2.1.2 and 2.2RC1: Update Your RubyGems</a>
</p>
</li>
+<li>
+<p>
+<a href="http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/1128">Detailed discussion on Lighthouse</a>
+</p>
+</li>
</ul></div>
</li>
</ul></div>
View
20 railties/doc/guides/html/actioncontroller_basics.html
@@ -723,7 +723,7 @@ <h2 id="_cookies">5. Cookies</h2>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
-<div class="para"><p>Note that while for session values, you set the key to <tt>nil</tt>, to delete a cookie value, you should use <tt>cookies.delete(:key)</tt>.</p></div>
+<div class="para"><p>Note that while for session values you set the key to <tt>nil</tt>, to delete a cookie value you should use <tt>cookies.delete(:key)</tt>.</p></div>
</div>
<h2 id="_filters">6. Filters</h2>
<div class="sectionbody">
@@ -767,7 +767,7 @@ <h2 id="_filters">6. Filters</h2>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
-<div class="para"><p>In this example, the filter is added to ApplicationController and thus all controllers in the application. This will make everything in the application require the user to be logged in in order to use it. For obvious reasons (the user wouldn't be able to log in in the first place!), not all controllers or actions should require this. You can prevent this filter from running before particular actions with <tt>skip_before_filter</tt> :</p></div>
+<div class="para"><p>In this example, the filter is added to ApplicationController and thus all controllers in the application. This will make everything in the application require the user to be logged in in order to use it. For obvious reasons (the user wouldn't be able to log in in the first place!), not all controllers or actions should require this. You can prevent this filter from running before particular actions with <tt>skip_before_filter</tt>:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -779,7 +779,7 @@ <h2 id="_filters">6. Filters</h2>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
-<div class="para"><p>Now, the <tt>LoginsController</tt>'s "new" and "create" actions will work as before without requiring the user to be logged in. The <tt>:only</tt> option is used to only skip this filter for these actions, and there is also an <tt>:except</tt> option which works the other way. These options can be used when adding filters too, so you can add a filter which only runs for selected actions in the first place.</p></div>
+<div class="para"><p>Now, the LoginsController's <tt>new</tt> and <tt>create</tt> actions will work as before without requiring the user to be logged in. The <tt>:only</tt> option is used to only skip this filter for these actions, and there is also an <tt>:except</tt> option which works the other way. These options can be used when adding filters too, so you can add a filter which only runs for selected actions in the first place.</p></div>
<h3 id="_after_filters_and_around_filters">6.1. After Filters and Around Filters</h3>
<div class="para"><p>In addition to the before filters, you can run filters after an action has run or both before and after. The after filter is similar to the before filter, but because the action has already been run it has access to the response data that's about to be sent to the client. Obviously, after filters can not stop the action from running. Around filters are responsible for running the action, but they can choose not to, which is the around filter's way of stopping it.</p></div>
<div class="listingblock">
@@ -872,7 +872,7 @@ <h2 id="_verification">7. Verification</h2>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
-<div class="para"><p>Now the <tt>create</tt> action won't run unless the "username" and "password" parameters are present, and if they're not, an error message will be added to the flash and the "new" action will be rendered. But there's something rather important missing from the verification above: It will be used for <strong>every</strong> action in LoginsController, which is not what we want. You can limit which actions it will be used for with the <tt>:only</tt> and <tt>:except</tt> options just like a filter:</p></div>
+<div class="para"><p>Now the <tt>create</tt> action won't run unless the "username" and "password" parameters are present, and if they're not, an error message will be added to the flash and the <tt>new</tt> action will be rendered. But there's something rather important missing from the verification above: It will be used for <strong>every</strong> action in LoginsController, which is not what we want. You can limit which actions it will be used for with the <tt>:only</tt> and <tt>:except</tt> options just like a filter:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -934,7 +934,7 @@ <h3 id="_the_tt_request_tt_object">9.1. The <tt>request</tt> Object</h3>
</li>
<li>
<p>
-domain - The hostname without the first segment (usually "www").
+domain(n=2) - The hostname's first <tt>n</tt> segments, starting from the right (the TLD)
</p>
</li>
<li>
@@ -949,7 +949,7 @@ <h3 id="_the_tt_request_tt_object">9.1. The <tt>request</tt> Object</h3>
</li>
<li>
<p>
-get?, post?, put?, delete?, head? - Returns true if the HTTP method is get/post/put/delete/head.
+get?, post?, put?, delete?, head? - Returns true if the HTTP method is GET/POST/PUT/DELETE/HEAD.
</p>
</li>
<li>
@@ -964,7 +964,7 @@ <h3 id="_the_tt_request_tt_object">9.1. The <tt>request</tt> Object</h3>
</li>
<li>
<p>
-protocol - The protocol used for the request.
+protocol - Returns a string containing the prototol used plus "://", for example "http://"
</p>
</li>
<li>
@@ -1118,7 +1118,7 @@ <h3 id="_sending_files">11.1. Sending Files</h3>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip" />
</td>
-<td class="content">It is not recommended that you stream static files through Rails if you can instead keep them in a public folder on your web server. It is much more efficient to let the user download the file directly using Apache or another web server, keeping the request from unnecessarily going through the whole Rails stack.</td>
+<td class="content">It is not recommended that you stream static files through Rails if you can instead keep them in a public folder on your web server. It is much more efficient to let the user download the file directly using Apache or another web server, keeping the request from unnecessarily going through the whole Rails stack. Although if you do need the request to go through Rails for some reason, you can set the <tt>:x_sendfile</tt> option to true, and Rails will let the web server handle sending the file to the user, freeing up the Rails process to do other things. Note that your web server needs to support the <tt>X-Sendfile</tt> header for this to work, and you still have to be careful not to use user input in a way that lets someone retrieve arbitrary files.</td>
</tr></table>
</div>
<h3 id="_restful_downloads">11.2. RESTful Downloads</h3>
@@ -1166,7 +1166,7 @@ <h3 id="_restful_downloads">11.2. RESTful Downloads</h3>
</div>
<h2 id="_parameter_filtering">12. Parameter Filtering</h2>
<div class="sectionbody">
-<div class="para"><p>Rails keeps a log file for each environment (development, test and production) in the "log" folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. The <tt>filter_parameter_logging</tt> method can be used to filter out sensitive information from the log. It works by replacing certain values in the <tt>params</tt> hash with "[FILTERED]" as they are written to the log. As an example, let's see how to filter all parameters with keys that include "password":</p></div>
+<div class="para"><p>Rails keeps a log file for each environment (development, test and production) in the <tt>log</tt> folder. These are extremely useful when debugging what's actually going on in your application, but in a live application you may not want every bit of information to be stored in the log file. The <tt>filter_parameter_logging</tt> method can be used to filter out sensitive information from the log. It works by replacing certain values in the <tt>params</tt> hash with "[FILTERED]" as they are written to the log. As an example, let's see how to filter all parameters with keys that include "password":</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -1178,7 +1178,7 @@ <h2 id="_parameter_filtering">12. Parameter Filtering</h2>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
-<div class="para"><p>The method works recursively through all levels of the params hash and takes an optional second parameter which is used as the replacement string if present. It can also take a block which receives each key in return and replaces those for which the block returns true.</p></div>
+<div class="para"><p>The method works recursively through all levels of the params hash and takes an optional second parameter which is used as the replacement string if present. It can also take a block which receives each key in turn and replaces those for which the block returns true.</p></div>
</div>
<h2 id="_rescue">13. Rescue</h2>
<div class="sectionbody">
View
454 railties/doc/guides/html/activerecord_validations_callbacks.html
@@ -267,6 +267,53 @@ <h2 id="site_title_tagline">Sustainable productivity for web-application develop
<a href="#_writing_your_own_validation_methods">Writing your own validation methods</a>
</li>
<li>
+ <a href="#_using_the_tt_errors_tt_collection">Using the <tt>errors</tt> collection</a>
+ </li>
+ <li>
+ <a href="#_callbacks">Callbacks</a>
+ <ul>
+
+ <li><a href="#_callbacks_registration">Callbacks registration</a></li>
+
+ <li><a href="#_registering_callbacks_by_overriding_the_callback_methods">Registering callbacks by overriding the callback methods</a></li>
+
+ <li><a href="#_registering_callbacks_by_using_macro_style_class_methods">Registering callbacks by using macro-style class methods</a></li>
+
+ </ul>
+ </li>
+ <li>
+ <a href="#_available_callbacks">Available callbacks</a>
+ <ul>
+
+ <li><a href="#_callbacks_called_both_when_creating_or_updating_a_record">Callbacks called both when creating or updating a record.</a></li>
+
+ <li><a href="#_callbacks_called_only_when_creating_a_new_record">Callbacks called only when creating a new record.</a></li>
+
+ <li><a href="#_callbacks_called_only_when_updating_an_existing_record">Callbacks called only when updating an existing record.</a></li>
+
+ <li><a href="#_callbacks_called_when_removing_a_record_from_the_database">Callbacks called when removing a record from the database.</a></li>
+
+ <li><a href="#_the_tt_after_initialize_tt_and_tt_after_find_tt_callbacks">The <tt>after_initialize</tt> and <tt>after_find</tt> callbacks</a></li>
+
+ </ul>
+ </li>
+ <li>
+ <a href="#_halting_execution">Halting Execution</a>
+ </li>
+ <li>
+ <a href="#_callback_classes">Callback classes</a>
+ </li>
+ <li>
+ <a href="#_observers">Observers</a>
+ <ul>
+
+ <li><a href="#_registering_observers">Registering observers</a></li>
+
+ <li><a href="#_where_to_put_the_observers_source_files">Where to put the observers' source files</a></li>
+
+ </ul>
+ </li>
+ <li>
<a href="#_changelog">Changelog</a>
</li>
</ol>
@@ -358,7 +405,15 @@ <h3 id="_when_does_validation_happens">2.1. When does validation happens?</h3>
&gt;&gt; p.new_record?
=&gt; false</tt></pre>
</div></div>
-<div class="para"><p>Saving new records means sending an SQL insert operation to the database, while saving existing records (by calling either <tt>save</tt>, <tt>update_attribute</tt> or <tt>update_attributes</tt>) will result in a SQL update operation. Active Record will use this facts to perform validations upon your objects, avoiding then to be recorded to the database if their inner state is invalid in some way. You can specify validations that will be beformed every time a object is saved, just when you're creating a new record or when you're updating an existing one.</p></div>
+<div class="para"><p>Saving new records means sending an SQL insert operation to the database, while saving existing records (by calling either <tt>save</tt> or <tt>update_attributes</tt>) will result in a SQL update operation. Active Record will use this facts to perform validations upon your objects, avoiding then to be recorded to the database if their inner state is invalid in some way. You can specify validations that will be beformed every time a object is saved, just when you're creating a new record or when you're updating an existing one.</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="./images/icons/caution.png" alt="Caution" />
+</td>
+<td class="content">There are four methods that when called will trigger validation: <tt>save</tt>, <tt>save!</tt>, <tt>update_attributes</tt> and <tt>update_attributes!</tt>. There is one method left, which is <tt>update_attribute</tt>. This method will update the value of an attribute without triggering any validation, so be careful when using <tt>update_attribute</tt>, since it can let you save your objects in an invalid state.</td>
+</tr></table>
+</div>
<h3 id="_the_meaning_of_em_valid_em">2.2. The meaning of <em>valid</em></h3>
<div class="para"><p>For verifying if an object is valid, Active Record uses the <tt>valid?</tt> method, which basically looks inside the object to see if it has any validation errors. These errors live in a collection that can be accessed through the <tt>errors</tt> instance method. The proccess is really simple: If the <tt>errors</tt> method returns an empty collection, the object is valid and can be saved. Each time a validation fails, an error message is added to the <tt>errors</tt> collection.</p></div>
</div>
@@ -719,7 +774,7 @@ <h2 id="_writing_your_own_validation_methods">6. Writing your own validation met
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
-<div class="para"><p>If your validation rules are too complicated and you want to break it in small methods, you can implement all of them and call one of <tt>validate</tt>, <tt>validate_on_create</tt> or <tt>validate_on_update</tt> methods, passing it the symbols for the methods' names.</p></div>
+<div class="para"><p>If your validation rules are too complicated and you want to break them in small methods, you can implement all of them and call one of <tt>validate</tt>, <tt>validate_on_create</tt> or <tt>validate_on_update</tt> methods, passing it the symbols for the methods' names.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -738,7 +793,400 @@ <h2 id="_writing_your_own_validation_methods">6. Writing your own validation met
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
</div>
-<h2 id="_changelog">7. Changelog</h2>
+<h2 id="_using_the_tt_errors_tt_collection">7. Using the <tt>errors</tt> collection</h2>
+<div class="sectionbody">
+<div class="para"><p>You can do more than just call <tt>valid?</tt> upon your objects based on the existance of the <tt>errors</tt> collection. Here is a list of the other available methods that you can use to manipulate errors or ask for an object's state.</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>add_to_base</tt> lets you add errors messages that are related to the object's state as a whole, instead of being related to a specific attribute. You can use this method when you want to say that the object is invalid, no matter the values of it's attributes. <tt>add_to_base</tt> receives a string with the message.
+</p>
+</li>
+</ul></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> a_method_used_for_validation_purposes
+ errors<span style="color: #990000">.</span>add_to_base<span style="color: #990000">(</span><span style="color: #FF0000">"This person is invalid because ..."</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>add</tt> lets you manually add messages that are related to particular attributes. When writing those messages, keep in mind that Rails will prepend them with the name of the attribute that holds the error, so write it in a way that makes sense. <tt>add</tt> receives a symbol with the name of the attribute that you want to add the message to and the message itself.
+</p>
+</li>
+</ul></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> a_method_used_for_validation_purposes
+ errors<span style="color: #990000">.</span>add<span style="color: #990000">(:</span>name<span style="color: #990000">,</span> <span style="color: #FF0000">"can't have the characters !@#$%*()_-+="</span><span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>invalid?</tt> is used when you want to check if a particular attribute is invalid. It receives a symbol with the name of the attribute that you want to check.
+</p>
+</li>
+</ul></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
+ validates_presence_of <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>email
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+person <span style="color: #990000">=</span> Person<span style="color: #990000">.</span>new<span style="color: #990000">(:</span>name <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"John Doe"</span><span style="color: #990000">)</span>
+person<span style="color: #990000">.</span>invalid?<span style="color: #990000">(:</span>email<span style="color: #990000">)</span> <span style="font-style: italic"><span style="color: #9A1900"># =&gt; true</span></span>
+</tt></pre></div></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>on</tt> is used when you want to check the error messages for a specific attribute. It will return different kinds of objects depending on the state of the <tt>errors</tt> collection for the given attribute. If there are no errors related to the attribute, <tt>on</tt> will return <tt>nil</tt>. If there is just one errors message for this attribute, <tt>on</tt> will return a string with the message. When <tt>errors</tt> holds two or more error messages for the attribute, <tt>on</tt> will return an array of strings, each one with one error message.
+</p>
+</li>
+</ul></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
+ validates_presence_of <span style="color: #990000">:</span>name
+ validates_length_of <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>minimum <span style="color: #990000">=&gt;</span> <span style="color: #993399">3</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+person <span style="color: #990000">=</span> Person<span style="color: #990000">.</span>new<span style="color: #990000">(:</span>name <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"John Doe"</span><span style="color: #990000">)</span>
+person<span style="color: #990000">.</span>valid? <span style="font-style: italic"><span style="color: #9A1900"># =&gt; true</span></span>
+person<span style="color: #990000">.</span>errors<span style="color: #990000">.</span>on<span style="color: #990000">(:</span>name<span style="color: #990000">)</span> <span style="font-style: italic"><span style="color: #9A1900"># =&gt; nil</span></span>
+
+person <span style="color: #990000">=</span> Person<span style="color: #990000">.</span>new<span style="color: #990000">(:</span>name <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"JD"</span><span style="color: #990000">)</span>
+person<span style="color: #990000">.</span>valid? <span style="font-style: italic"><span style="color: #9A1900"># =&gt; false</span></span>
+person<span style="color: #990000">.</span>errors<span style="color: #990000">.</span>on<span style="color: #990000">(:</span>name<span style="color: #990000">)</span> <span style="font-style: italic"><span style="color: #9A1900"># =&gt; "is too short (minimum is 3 characters)"</span></span>
+
+person <span style="color: #990000">=</span> Person<span style="color: #990000">.</span>new
+person<span style="color: #990000">.</span>valid? <span style="font-style: italic"><span style="color: #9A1900"># =&gt; false</span></span>
+person<span style="color: #990000">.</span>errors<span style="color: #990000">.</span>on<span style="color: #990000">(:</span>name<span style="color: #990000">)</span> <span style="font-style: italic"><span style="color: #9A1900"># =&gt; ["can't be blank", "is too short (minimum is 3 characters)"]</span></span>
+</tt></pre></div></div>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>clear</tt> is used when you intentionally wants to clear all the messages in the <tt>errors</tt> collection.
+</p>
+</li>
+</ul></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Person <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
+ validates_presence_of <span style="color: #990000">:</span>name
+ validates_length_of <span style="color: #990000">:</span>name<span style="color: #990000">,</span> <span style="color: #990000">:</span>minimum <span style="color: #990000">=&gt;</span> <span style="color: #993399">3</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+
+person <span style="color: #990000">=</span> Person<span style="color: #990000">.</span>new
+puts person<span style="color: #990000">.</span>valid? <span style="font-style: italic"><span style="color: #9A1900"># =&gt; false</span></span>
+person<span style="color: #990000">.</span>errors<span style="color: #990000">.</span>on<span style="color: #990000">(:</span>name<span style="color: #990000">)</span> <span style="font-style: italic"><span style="color: #9A1900"># =&gt; ["can't be blank", "is too short (minimum is 3 characters)"]</span></span>
+person<span style="color: #990000">.</span>errors<span style="color: #990000">.</span>clear
+person<span style="color: #990000">.</span>errors <span style="font-style: italic"><span style="color: #9A1900"># =&gt; nil</span></span>
+</tt></pre></div></div>
+</div>
+<h2 id="_callbacks">8. Callbacks</h2>
+<div class="sectionbody">
+<div class="para"><p>Callbacks are methods that get called at certain moments of an object's lifecycle. With callbacks it's possible to write code that will run whenever an Active Record object is created, saved, updated, deleted or loaded from the database.</p></div>
+<h3 id="_callbacks_registration">8.1. Callbacks registration</h3>
+<div class="para"><p>In order to use the available callbacks, you need to registrate them. There are two ways of doing that.</p></div>
+<h3 id="_registering_callbacks_by_overriding_the_callback_methods">8.2. Registering callbacks by overriding the callback methods</h3>
+<div class="para"><p>You can specify the callback method direcly, by overriding it. Let's see how it works using the <tt>before_validation</tt> callback, which will surprisingly run right before any validation is done.</p></div>
+<div class="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> User <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
+ validates_presence_of <span style="color: #990000">:</span>login<span style="color: #990000">,</span> <span style="color: #990000">:</span>email
+
+ protected
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> before_validation
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>login<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">nil</span></span><span style="color: #990000">?</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>login <span style="color: #990000">=</span> email <span style="font-weight: bold"><span style="color: #0000FF">unless</span></span> email<span style="color: #990000">.</span>blank?
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_registering_callbacks_by_using_macro_style_class_methods">8.3. Registering callbacks by using macro-style class methods</h3>
+<div class="para"><p>The other way you can register a callback method is by implementing it as an ordinary method, and then using a macro-style class method to register it as a callback. The last example could be written like that:</p></div>
+<div class="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> User <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
+ validates_presence_of <span style="color: #990000">:</span>login<span style="color: #990000">,</span> <span style="color: #990000">:</span>email
+
+ before_validation <span style="color: #990000">:</span>ensure_login_has_a_value
+
+ protected
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> ensure_login_has_a_value
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>login<span style="color: #990000">.</span><span style="font-weight: bold"><span style="color: #0000FF">nil</span></span><span style="color: #990000">?</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>login <span style="color: #990000">=</span> email <span style="font-weight: bold"><span style="color: #0000FF">unless</span></span> email<span style="color: #990000">.</span>blank?
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>The macro-style class methods can also receive a block. Rails best practices say that you should only use this style of registration if the code inside your block is so short that it fits in just one line.</p></div>
+<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> User <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
+ validates_presence_of <span style="color: #990000">:</span>login<span style="color: #990000">,</span> <span style="color: #990000">:</span>email
+
+ before_create <span style="color: #FF0000">{</span><span style="color: #990000">|</span>user<span style="color: #990000">|</span> user<span style="color: #990000">.</span>name <span style="color: #990000">=</span> user<span style="color: #990000">.</span>login<span style="color: #990000">.</span>capitalize <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> user<span style="color: #990000">.</span>name<span style="color: #990000">.</span>blank?<span style="color: #FF0000">}</span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>In Rails, the preferred way of registering callbacks is by using macro-style class methods. The main advantages of using macro-style class methods are:</p></div>
+<div class="ilist"><ul>
+<li>
+<p>
+You can add more than one method for each type of callback. Those methods will be queued for execution at the same order they were registered.
+</p>
+</li>
+<li>
+<p>
+Readability, since your callback declarations will live at the beggining of your models' files.
+</p>
+</li>
+</ul></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<img src="./images/icons/caution.png" alt="Caution" />
+</td>
+<td class="content">Remember to always declare the callback methods as being protected or private. These methods should never be public, otherwise it will be possible to call them from code outside the model, violating object encapsulation and exposing implementation details.</td>
+</tr></table>
+</div>
+</div>
+<h2 id="_available_callbacks">9. Available callbacks</h2>
+<div class="sectionbody">
+<div class="para"><p>Here is a list with all the available Active Record callbacks, listed in the same order in which they will get called during the respective operations.</p></div>
+<h3 id="_callbacks_called_both_when_creating_or_updating_a_record">9.1. Callbacks called both when creating or updating a record.</h3>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>before_validation</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>after_validation</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>before_save</tt>
+</p>
+</li>
+<li>
+<p>
+<strong>INSERT OR UPDATE OPERATION</strong>
+</p>
+</li>
+<li>
+<p>
+<tt>after_save</tt>
+</p>
+</li>
+</ul></div>
+<h3 id="_callbacks_called_only_when_creating_a_new_record">9.2. Callbacks called only when creating a new record.</h3>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>before_validation_on_create</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>after_validation_on_create</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>before_create</tt>
+</p>
+</li>
+<li>
+<p>
+<strong>INSERT OPERATION</strong>
+</p>
+</li>
+<li>
+<p>
+<tt>after_create</tt>
+</p>
+</li>
+</ul></div>
+<h3 id="_callbacks_called_only_when_updating_an_existing_record">9.3. Callbacks called only when updating an existing record.</h3>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>before_validation_on_update</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>after_validation_on_update</tt>
+</p>
+</li>
+<li>
+<p>
+<tt>before_update</tt>
+</p>
+</li>
+<li>
+<p>
+<strong>UPDATE OPERATION</strong>
+</p>
+</li>
+<li>
+<p>
+<tt>after_update</tt>
+</p>
+</li>
+</ul></div>
+<h3 id="_callbacks_called_when_removing_a_record_from_the_database">9.4. Callbacks called when removing a record from the database.</h3>
+<div class="ilist"><ul>
+<li>
+<p>
+<tt>before_destroy</tt>
+</p>
+</li>
+<li>
+<p>
+<strong>DELETE OPERATION</strong>
+</p>
+</li>
+<li>
+<p>
+<tt>after_destroy</tt>
+</p>
+</li>
+</ul></div>
+<div class="para"><p>The <tt>before_destroy</tt> and <tt>after_destroy</tt> callbacks will only be called if you delete the model using either the <tt>destroy</tt> instance method or one of the <tt>destroy</tt> or <tt>destroy_all</tt> class methods of your Active Record class. If you use <tt>delete</tt> or <tt>delete_all</tt> no callback operations will run, since Active Record will not instantiate any objects, accessing the records to be deleted directly in the database.</p></div>
+<h3 id="_the_tt_after_initialize_tt_and_tt_after_find_tt_callbacks">9.5. The <tt>after_initialize</tt> and <tt>after_find</tt> callbacks</h3>
+<div class="para"><p>The <tt>after_initialize</tt> callback will be called whenever an Active Record object is instantiated, either by direcly using <tt>new</tt> or when a record is loaded from the database. It can be useful to avoid the need to directly override your Active Record <tt>initialize</tt> method.</p></div>
+<div class="para"><p>The <tt>after_find</tt> callback will be called whenever Active Record loads a record from the database. When used together with <tt>after_initialize</tt> it will run first, since Active Record will first read the record from the database and them create the model object that will hold it.</p></div>
+<div class="para"><p>The <tt>after_initialize</tt> and <tt>after_find</tt> callbacks are a bit different from the others, since the only way to register those callbacks is by defining them as methods. If you try to register <tt>after_initialize</tt> or <tt>after_find</tt> using macro-style class methods, they will just be ignored. This behaviour is due to performance reasons, since <tt>after_initialize</tt> and <tt>after_find</tt> will both be called for each record found in the database, significantly slowing down the queries.</p></div>
+</div>
+<h2 id="_halting_execution">10. Halting Execution</h2>
+<div class="sectionbody">
+<div class="para"><p>As you start registering new callbacks for your models, they will be queued for execution. This queue will include all your model's validations, the registered callbacks and the database operation to be executed. However, if at any moment one of the callback methods returns a boolean <tt>false</tt> (not <tt>nil</tt>) value, this execution chain will be halted and the desired operation will not complete: your model will not get persisted in the database, or your records will not get deleted and so on.</p></div>
+</div>
+<h2 id="_callback_classes">11. Callback classes</h2>
+<div class="sectionbody">
+<div class="para"><p>Sometimes the callback methods that you'll write will be useful enough to be reused at other models. Active Record makes it possible to create classes that encapsulate the callback methods, so it becomes very easy to reuse them.</p></div>
+<div class="para"><p>Here's an example where we create a class with a after_destroy callback for a PictureFile model.</p></div>
+<div class="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> PictureFileCallbacks
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> after_destroy<span style="color: #990000">(</span>picture_file<span style="color: #990000">)</span>
+ File<span style="color: #990000">.</span>delete<span style="color: #990000">(</span>picture_file<span style="color: #990000">.</span>filepath<span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> File<span style="color: #990000">.</span>exists?<span style="color: #990000">(</span>picture_file<span style="color: #990000">.</span>filepath<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>When declared inside a class the callback method will receive the model object as a parameter. We can now use it this way:</p></div>
+<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> PictureFile <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
+ after_destroy PictureFileCallbacks<span style="color: #990000">.</span>new
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Note that we needed to instantiate a new PictureFileCallbacks object, since we declared our callback as an instance method. Sometimes it will make more sense to have it as a class method.</p></div>
+<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> PictureFileCallbacks
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> <span style="font-weight: bold"><span style="color: #0000FF">self</span></span><span style="color: #990000">.</span>after_destroy<span style="color: #990000">(</span>picture_file<span style="color: #990000">)</span>
+ File<span style="color: #990000">.</span>delete<span style="color: #990000">(</span>picture_file<span style="color: #990000">.</span>filepath<span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> File<span style="color: #990000">.</span>exists?<span style="color: #990000">(</span>picture_file<span style="color: #990000">.</span>filepath<span style="color: #990000">)</span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If the callback method is declared this way, it won't be necessary to instantiate a PictureFileCallbacks object.</p></div>
+<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> PictureFile <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
+ after_destroy PictureFileCallbacks
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>You can declare as many callbacks as you want inside your callback classes.</p></div>
+</div>
+<h2 id="_observers">12. Observers</h2>
+<div class="sectionbody">
+<div class="para"><p>Active Record callbacks are a powerful feature, but they can pollute your model implementation with code that's not directly related to the model's purpose. In object-oriented software, it's always a good idea to design your classes with a single responsability in the whole system. For example, it wouldn't make much sense to have a <tt>User</tt> model with a method that writes data about a login attempt to a log file. Whenever you're using callbacks to write code that's not directly related to your model class purposes, it may be a good moment to create an Observer.</p></div>
+<div class="para"><p>An Active Record Observer is an object that links itself to a model and register it's methods for callbacks. Your model's implementation remain clean, while you can reuse the code in the Observer to add behaviuor to more than one model class. Ok, you may say that we can also do that using callback classes, but it would still force us to add code to our model's implementation.</p></div>
+<div class="para"><p>Observer classes are subclasses of the <tt>ActiveRecord::Observer</tt> class. When this class is subclassed, Active Record will look at the name of the new class and then strip the <em>Observer</em> part to find the name of the Active Record class to observe.</p></div>
+<div class="para"><p>Consider a <tt>Registration</tt> model, where we want to send an email everytime a new registration is created. Since sending emails is not directly related to our model's purpose, we could create an Observer to do just that:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> RegistrationObserver <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Observer
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> after_create<span style="color: #990000">(</span>model<span style="color: #990000">)</span>
+ <span style="font-style: italic"><span style="color: #9A1900"># code to send registration confirmation emails...</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>Like in callback classes, the observer's methods receive the observed model as a parameter.</p></div>
+<div class="para"><p>Sometimes using the ModelName + Observer naming convention won't be the best choice, mainly when you want to use the same observer for more than one model class. It's possible to explicity specify the models that our observer should observe.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> Auditor <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Observer
+ observe User<span style="color: #990000">,</span> Registration<span style="color: #990000">,</span> Invoice
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<h3 id="_registering_observers">12.1. Registering observers</h3>
+<div class="para"><p>If you payed attention, you may be wondering where Active Record Observers are referenced in our applications, so they get instantiate and begin to interact with our models. For observers to work we need to register then in our application's <strong>config/environment.rb</strong> file. In this file there is a commented out line where we can define the observers that our application should load at start-up.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-style: italic"><span style="color: #9A1900"># Activate observers that should always be running</span></span>
+config<span style="color: #990000">.</span>active_record<span style="color: #990000">.</span>observers <span style="color: #990000">=</span> <span style="color: #990000">:</span>registration_observer<span style="color: #990000">,</span> <span style="color: #990000">:</span>auditor
+</tt></pre></div></div>
+<h3 id="_where_to_put_the_observers_source_files">12.2. Where to put the observers' source files</h3>
+<div class="para"><p>By convention, you should always save your observers' source files inside <strong>app/models</strong>.</p></div>
+</div>
+<h2 id="_changelog">13. Changelog</h2>
<div class="sectionbody">
<div class="para"><p><a href="http://rails.lighthouseapp.com/projects/16213/tickets/26-active-record-validations-and-callbacks">http://rails.lighthouseapp.com/projects/16213/tickets/26-active-record-validations-and-callbacks</a></p></div>
</div>
View
21 railties/doc/guides/html/association_basics.html
@@ -687,8 +687,8 @@ <h3 id="_self_joins">2.10. Self Joins</h3>
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> Employee <span style="color: #990000">&lt;</span> ActiveRecord<span style="color: #990000">::</span>Base
- has_many <span style="color: #990000">:</span>subordinates<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"User"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>foreign_key <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"manager_id"</span>
- belongs_to <span style="color: #990000">:</span>manager<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"User"</span>
+ has_many <span style="color: #990000">:</span>subordinates<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"Employee"</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>foreign_key <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"manager_id"</span>
+ belongs_to <span style="color: #990000">:</span>manager<span style="color: #990000">,</span> <span style="color: #990000">:</span>class_name <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">"Employee"</span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>With this setup, you can retrieve <tt>@employee.subordinates</tt> and <tt>@employee.manager</tt>.</p></div>
@@ -742,7 +742,9 @@ <h3 id="_controlling_caching">3.1. Controlling Caching</h3>
<h3 id="_avoiding_name_collisions">3.2. Avoiding Name Collisions</h3>
<div class="para"><p>You are not free to use just any name for your associations. Because creating an association adds a method with that name to the model, it is a bad idea to give an association a name that is already used for an instance method of <tt>ActiveRecord::Base</tt>. The association method would override the base method and break things. For instance, <tt>attributes</tt> or <tt>connection</tt> are bad names for associations.</p></div>
<h3 id="_updating_the_schema">3.3. Updating the Schema</h3>
-<div class="para"><p>Associations are extremely useful, but they are not magic. You are responsible for maintaining your database schema to match your associations. In practice, this means two things. First, you need to create foreign keys as appropriate:</p></div>
+<div class="para"><p>Associations are extremely useful, but they are not magic. You are responsible for maintaining your database schema to match your associations. In practice, this means two things, depending on what sort of associations you are creating. For <tt>belongs_to</tt> associations you need to create foreign keys, and for <tt>has_and_belongs_to_many</tt> associations you need to create the appropriate join table.</p></div>
+<h4 id="_creating_foreign_keys_for_tt_belongs_to_tt_associations">3.3.1. Creating Foreign Keys for <tt>belongs_to</tt> Associations</h4>
+<div class="para"><p>When you declare a <tt>belongs_to</tt> association, you need to create foreign keys as appropriate. For example, consider this model:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -761,9 +763,9 @@ <h3 id="_updating_the_schema">3.3. Updating the Schema</h3>
<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">class</span></span> CreateOrders <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>orders <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>order_date <span style="color: #990000">:</span>datetime
- t<span style="color: #990000">.</span>order_number <span style="color: #990000">:</span>string
- t<span style="color: #990000">.</span>customer_id <span style="color: #990000">:</span>integer
+ t<span style="color: #990000">.</span>datetime <span style="color: #990000">:</span>order_date
+ t<span style="color: #990000">.</span>string <span style="color: #990000">:</span>order_number
+ t<span style="color: #990000">.</span>integer <span style="color: #990000">:</span>customer_id
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
@@ -773,7 +775,8 @@ <h3 id="_updating_the_schema">3.3. Updating the Schema</h3>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>If you create an association some time after you build the underlying model, you need to remember to create an <tt>add_column</tt> migration to provide the necessary foreign key.</p></div>
-<div class="para"><p>Second, if you create a <tt>has_and_belongs_to_many</tt> association, you need to explicitly create the joining table. Unless the name of the join table is explicitly specified by using the <tt>:join_table</tt> option, Active Record create the name by using the lexical order of the class names. So a join between customer and order models will give the default join table name of "customers_orders" because "c" outranks "o" in lexical ordering.</p></div>
+<h4 id="_creating_join_tables_for_tt_has_and_belongs_to_many_tt_associations">3.3.2. Creating Join Tables for <tt>has_and_belongs_to_many</tt> Associations</h4>
+<div class="para"><p>If you create a <tt>has_and_belongs_to_many</tt> association, you need to explicitly create the joining table. Unless the name of the join table is explicitly specified by using the <tt>:join_table</tt> option, Active Record create the name by using the lexical order of the class names. So a join between customer and order models will give the default join table name of "customers_orders" because "c" outranks "o" in lexical ordering.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
@@ -1938,7 +1941,7 @@ <h5 id="_tt_limit_tt"><tt>:limit</tt></h5>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<h5 id="_tt_offset_tt"><tt>:offset</tt></h5>
-<div class="para"><p>The <tt>:offset</tt> option lets you specify the starting offset for fetching objects via an association. For example, if you set <tt>:offset &#8658; 11</tt>, it will skip the first 10 records.</p></div>
+<div class="para"><p>The <tt>:offset</tt> option lets you specify the starting offset for fetching objects via an association. For example, if you set <tt>:offset &#8658; 11</tt>, it will skip the first 11 records.</p></div>
<h5 id="_tt_order_tt_2"><tt>:order</tt></h5>
<div class="para"><p>The <tt>:order</tt> option dictates the order in which associated objects will be received (in the syntax used by a SQL <tt>ORDER BY</tt> clause).</p></div>
<div class="listingblock">
@@ -2409,7 +2412,7 @@ <h5 id="_tt_limit_tt_2"><tt>:limit</tt></h5>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<h5 id="_tt_offset_tt_2"><tt>:offset</tt></h5>
-<div class="para"><p>The <tt>:offset</tt> option lets you specify the starting offset for fetching objects via an association. For example, if you set <tt>:offset &#8658; 11</tt>, it will skip the first 10 records.</p></div>
+<div class="para"><p>The <tt>:offset</tt> option lets you specify the starting offset for fetching objects via an association. For example, if you set <tt>:offset &#8658; 11</tt>, it will skip the first 11 records.</p></div>
<h5 id="_tt_order_tt_3"><tt>:order</tt></h5>
<div class="para"><p>The <tt>:order</tt> option dictates the order in which associated objects will be received (in the syntax used by a SQL <tt>ORDER BY</tt> clause).</p></div>
<div class="listingblock">
View
5 railties/doc/guides/html/authors.html
@@ -231,6 +231,11 @@ <h2 id="site_title_tagline">Sustainable productivity for web-application develop
<div class="para"><p>Tore Darell is an independent developer based in Menton, France who specialises in cruft-free web applications using Ruby, Rails
and unobtrusive JavaScript. His home on the internet is his blog <a href="http://tore.darell.no/">Sneaky Abstractions</a>.</p></div>
</div></div>
+<div class="sidebarblock" id="zilkey">
+<div class="sidebar-content">
+<div class="sidebar-title">Jeff Dean</div>
+<div class="para"><p>Jeff Dean is a software engineer with <a href="http://pivotallabs.com/">Pivotal Labs</a>.</p></div>
+</div></div>
</div>
</div>
View
124 railties/doc/guides/html/caching_with_rails.html
@@ -217,6 +217,9 @@ <h2 id="site_title_tagline">Sustainable productivity for web-application develop
</ul>
</li>
<li>
+ <a href="#_conditional_get_support">Conditional GET support</a>
+ </li>
+ <li>
<a href="#_advanced_caching">Advanced Caching</a>
</li>
</ol>
@@ -235,8 +238,8 @@ <h2 id="_basic_caching">1. Basic Caching</h2>
<div class="sectionbody">
<div class="para"><p>This is an introduction to the three types of caching techniques that Rails
provides by default without the use of any third party plugins.</p></div>
-<div class="para"><p>To get started make sure config.action_controller.perform_caching is set
-to true for your environment. This flag is normally set in the
+<div class="para"><p>To get started make sure <tt>config.action_controller.perform_caching</tt> is set
+to <tt>true</tt> for your environment. This flag is normally set in the
corresponding config/environments/*.rb and caching is disabled by default
there for development and test, and enabled for production.</p></div>
<div class="listingblock">
@@ -270,19 +273,19 @@ <h3 id="_page_caching">1.1. Page Caching</h3>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
<div class="para"><p>The first time anyone requests products/index, Rails will generate a file
-called index.html and the webserver will then look for that file before it
+called <tt>index.html</tt> and the webserver will then look for that file before it
passes the next request for products/index to your Rails application.</p></div>
<div class="para"><p>By default, the page cache directory is set to Rails.public_path (which is
-usually set to RAILS_ROOT + "/public") and this can be configured by
-changing the configuration setting ActionController::Base.page_cache_directory. Changing the
-default from /public helps avoid naming conflicts, since you may want to
-put other static html in /public, but changing this will require web
-server reconfiguration to let the web server know where to serve the
-cached files from.</p></div>
-<div class="para"><p>The Page Caching mechanism will automatically add a .html exxtension to
+usually set to <tt>RAILS_ROOT + "/public"</tt>) and this can be configured by
+changing the configuration setting <tt>config.action_controller.page_cache_directory</tt>.
+Changing the default from /public helps avoid naming conflicts, since you may
+want to put other static html in /public, but changing this will require web
+server reconfiguration to let the web server know where to serve the cached
+files from.</p></div>
+<div class="para"><p>The Page Caching mechanism will automatically add a <tt>.html</tt> exxtension to
requests for pages that do not have an extension to make it easy for the
webserver to find those pages and this can be configured by changing the
-configuration setting ActionController::Base.page_cache_extension.</p></div>
+configuration setting <tt>config.action_controller.page_cache_extension</tt>.</p></div>
<div class="para"><p>In order to expire this page when a new product is added we could extend our
example controler like this:</p></div>
<div class="listingblock">
@@ -337,8 +340,8 @@ <h3 id="_action_caching">1.2. Action Caching</h3>
<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
</tt></pre></div></div>
-<div class="para"><p>And you can also use :if (or :unless) to pass a Proc that specifies when the
-action should be cached. Also, you can use :layout &#8658; false to cache without
+<div class="para"><p>And you can also use <tt>:if</tt> (or <tt>:unless</tt>) to pass a Proc that specifies when the
+action should be cached. Also, you can use <tt>:layout &#8658; false</tt> to cache without
layout so that dynamic information in the layout such as logged in user info
or the number of items in the cart can be left uncached. This feature is
available as of Rails 2.2.</p></div>
@@ -377,7 +380,7 @@ <h3 id="_fragment_caching">1.3. Fragment Caching</h3>
</tt></pre></div></div>
<div class="para"><p>The cache block in our example will bind to the action that called it and is
written out to the same place as the Action Cache, which means that if you
-want to cache multiple fragments per action, you should provide an action_suffix to the cache call:</p></div>
+want to cache multiple fragments per action, you should provide an <tt>action_suffix</tt> to the cache call:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -386,18 +389,38 @@ <h3 id="_fragment_caching">1.3. Fragment Caching</h3>
<pre><tt><span style="color: #FF0000">&lt;% cache(:action =&gt;</span> <span style="color: #FF0000">'recent'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action_suffix <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'all_products'</span><span style="color: #990000">)</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">%&gt;</span>
All available products<span style="color: #990000">:</span>
</tt></pre></div></div>
-<div class="para"><p>and you can expire it using the expire_fragment method, like so:</p></div>
+<div class="para"><p>and you can expire it using the <tt>expire_fragment</tt> method, like so:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>expire_fragment<span style="color: #990000">(:</span>controller <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'products'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'recent'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action_suffix <span style="color: #990000">=&gt;</span> 'all_products<span style="color: #990000">)</span>
+</tt></pre></div></div>
+<div class="para"><p>If you don't want the cache block to bind to the action that called it, You can
+also use globally keyed fragments by calling the cache method with a key, like
+so:</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
-<pre><tt>expire_fragment<span style="color: #990000">(:</span>controller <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'producst'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action <span style="color: #990000">=&gt;</span> <span style="color: #FF0000">'recent'</span><span style="color: #990000">,</span> <span style="color: #990000">:</span>action_suffix <span style="color: #990000">=&gt;</span> 'all_products<span style="color: #990000">)</span>
+<pre><tt><span style="color: #FF0000">&lt;% cache(:key =&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">'all_available_products'</span><span style="color: #990000">,</span> <span style="color: #009900">@latest_product</span><span style="color: #990000">.</span>created_at<span style="color: #990000">].</span>join<span style="color: #990000">(</span><span style="color: #FF0000">':'</span><span style="color: #990000">))</span> <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">%&gt;</span>
+ All available products<span style="color: #990000">:</span>
+</tt></pre></div></div>
+<div class="para"><p>This fragment is then available to all actions in the ProductsController using
+the key and can be expired the same way:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 2.9
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>expire_fragment<span style="color: #990000">(:</span>key <span style="color: #990000">=&gt;</span> <span style="color: #990000">[</span><span style="color: #FF0000">'all_available_products'</span><span style="color: #990000">,</span> <span style="color: #009900">@latest_product</span><span style="color: #990000">.</span>created_at<span style="color: #990000">].</span>join<span style="color: #990000">(</span><span style="color: #FF0000">':'</span><span style="color: #990000">))</span>
</tt></pre></div></div>
<h3 id="_sweepers">1.4. Sweepers</h3>
<div class="para"><p>Cache sweeping is a mechanism which allows you to get around having a ton of
expire_{page,action,fragment} calls in your code by moving all the work
-required to expire cached content into a ActionController::Caching::Sweeper
+required to expire cached content into a <tt>ActionController::Caching::Sweeper</tt>
class that is an Observer and looks for changes to an object via callbacks,
and when a change occurs it expires the caches associated with that object n
an around or after filter.</p></div>
@@ -547,8 +570,7 @@ <h3 id="_cache_stores">1.6. Cache stores</h3>
<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> <span style="color: #990000">:</span>drb_store<span style="color: #990000">,</span> <span style="color: #FF0000">"druby://localhost:9192"</span>
</tt></pre></div></div>
<div class="para"><p>4) MemCached store: Works like DRbStore, but uses Danga's MemCache instead.
- Requires the ruby-memcache library:
- gem install ruby-memcache.</p></div>
+ Rails uses the bundled memcached-client gem by default.</p></div>
<div class="listingblock">
<div class="content"><!-- Generator: GNU source-highlight 2.9
by Lorenzo Bettini
@@ -564,8 +586,70 @@ <h3 id="_cache_stores">1.6. Cache stores</h3>
http://www.gnu.org/software/src-highlite -->
<pre><tt>ActionController<span style="color: #990000">::</span>Base<span style="color: #990000">.</span>cache_store <span style="color: #990000">=</span> MyOwnStore<span style="color: #990000">.</span>new<span style="color: #990000">(</span><span style="color: #FF0000">"parameter"</span><span style="color: #990000">)</span>
</tt></pre></div></div>
+<div class="para"><p><tt>Note: config.cache_store can be used in place of
+ActionController::Base.cache_store in your Rails::Initializer.run block in
+environment.rb</tt></p></div>
+</div>
+<h2 id="_conditional_get_support">2. Conditional GET support</h2>
+<div class="sectionbody">
+<div class="para"><p>Conditional GETs are a facility of the HTTP spec that provide a way for web
+servers to tell browsers that the response to a GET request hasn’t changed
+since the last request and can be safely pulled from the browser cache.</p></div>
+<div class="para"><p>They work by using the HTTP_IF_NONE_MATCH and HTTP_IF_MODIFIED_SINCE headers to
+pass back and forth both a unique content identifier and the timestamp of when
+the content was last changed. If the browser makes a request where the content
+identifier (etag) or last modified since timestamp matches the server’s version
+then the server only needs to send back an empty response with a not modified
+status.</p></div>
+<div class="para"><p>It is the server’s (i.e. our) responsibility to look for a last modified
+timestamp and the if-none-match header and determine whether or not to send
+back the full response. With conditional-get support in rails this is a pretty
+easy task:</p></div>
+<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> ProductsController <span style="color: #990000">&lt;</span> ApplicationController
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> show
+ <span style="color: #009900">@product</span> <span style="color: #990000">=</span> Product<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># If the request is stale according to the given timestamp and etag value</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># (i.e. it needs to be processed again) then execute this block</span></span>
+ <span style="font-weight: bold"><span style="color: #0000FF">if</span></span> stale?<span style="color: #990000">(:</span>last_modified <span style="color: #990000">=&gt;</span> <span style="color: #009900">@product</span><span style="color: #990000">.</span>updated_at<span style="color: #990000">.</span>utc<span style="color: #990000">,</span> <span style="color: #990000">:</span>etag <span style="color: #990000">=&gt;</span> <span style="color: #009900">@product</span><span style="color: #990000">)</span>
+ respond_to <span style="font-weight: bold"><span style="color: #0000FF">do</span></span> <span style="color: #990000">|</span>wants<span style="color: #990000">|</span>
+ <span style="font-style: italic"><span style="color: #9A1900"># ... normal response processing</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>
+
+ <span style="font-style: italic"><span style="color: #9A1900"># If the request is fresh (i.e. it's not modified) then you don't need to do</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># anything. The default render checks for this using the parameters</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># used in the previous call to stale? and will automatically send a</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># :not_modified. So that's it, you're done.</span></span>
+<span style="font-weight: bold"><span style="color: #0000FF">end</span></span>
+</tt></pre></div></div>
+<div class="para"><p>If you don’t have any special response processing and are using the default
+rendering mechanism (i.e. you’re not using respond_to or calling render
+yourself) then you’ve got an easy helper in fresh_when:</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> ProductsController <span style="color: #990000">&lt;</span> ApplicationController
+
+ <span style="font-style: italic"><span style="color: #9A1900"># This will automatically send back a :not_modified if the request is fresh,</span></span>
+ <span style="font-style: italic"><span style="color: #9A1900"># and will render the default template (product.*) if it's stale.</span></span>
+
+ <span style="font-weight: bold"><span style="color: #0000FF">def</span></span> show
+ <span style="color: #009900">@product</span> <span style="color: #990000">=</span> Product<span style="color: #990000">.</span>find<span style="color: #990000">(</span>params<span style="color: #990000">[:</span>id<span style="color: #990000">])</span>
+ fresh_when <span style="color: #990000">:</span>last_modified <span style="color: #990000">=&gt;</span> <span style="color: #009900">@product</span><span style="color: #990000">.</span>published_at<span style="color: #990000">.</span>utc<span style="color: #990000">,</span> <span <