aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/lib/action_controller/caching/actions.rb4
-rwxr-xr-xactionpack/lib/action_controller/request.rb69
-rw-r--r--actionpack/lib/action_controller/rescue.rb2
-rw-r--r--actionpack/lib/action_controller/resources.rb58
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/prototype_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb2
-rw-r--r--activemodel/lib/active_model/validations/uniqueness.rb4
-rwxr-xr-xactiverecord/lib/active_record/associations.rb15
-rw-r--r--activerecord/lib/active_record/associations/association_collection.rb36
-rw-r--r--activerecord/lib/active_record/associations/association_proxy.rb57
-rw-r--r--activerecord/lib/active_record/associations/has_many_association.rb14
-rwxr-xr-x[-rw-r--r--]activerecord/lib/active_record/base.rb61
-rw-r--r--activerecord/lib/active_record/calculations.rb4
-rw-r--r--activerecord/lib/active_record/callbacks.rb10
-rw-r--r--activerecord/lib/active_record/named_scope.rb26
-rw-r--r--activerecord/lib/active_record/transactions.rb2
-rw-r--r--activerecord/lib/active_record/validations.rb2
-rw-r--r--activeresource/lib/active_resource/base.rb80
-rw-r--r--activeresource/lib/active_resource/validations.rb44
-rw-r--r--activesupport/lib/active_support/string_inquirer.rb10
-rw-r--r--railties/doc/guides/routing/routing_outside_in.txt763
-rw-r--r--railties/environments/environment.rb3
-rw-r--r--railties/lib/commands/dbconsole.rb2
24 files changed, 1075 insertions, 199 deletions
diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb
index e72434074e..7c803a9830 100644
--- a/actionpack/lib/action_controller/caching/actions.rb
+++ b/actionpack/lib/action_controller/caching/actions.rb
@@ -38,8 +38,8 @@ module ActionController #:nodoc:
# caches_action :show, :cache_path => { :project => 1 }, :expires_in => 1.hour
# caches_action :feed, :cache_path => Proc.new { |controller|
# controller.params[:user_id] ?
- # controller.send(:user_list_url, c.params[:user_id], c.params[:id]) :
- # controller.send(:list_url, c.params[:id]) }
+ # controller.send(:user_list_url, controller.params[:user_id], controller.params[:id]) :
+ # controller.send(:list_url, controller.params[:id]) }
# end
#
# If you pass :layout => false, it will only cache your action content. It is useful when your layout has dynamic information.
diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb
index d793ade702..8e6cfb41dc 100755
--- a/actionpack/lib/action_controller/request.rb
+++ b/actionpack/lib/action_controller/request.rb
@@ -22,7 +22,7 @@ module ActionController
# such as { 'RAILS_ENV' => 'production' }.
attr_reader :env
- # The true HTTP request method as a lowercase symbol, such as <tt>:get</tt>.
+ # The true HTTP request \method as a lowercase symbol, such as <tt>:get</tt>.
# UnknownHttpMethod is raised for invalid methods not listed in ACCEPTED_HTTP_METHODS.
def request_method
method = @env['REQUEST_METHOD']
@@ -32,7 +32,7 @@ module ActionController
end
memoize :request_method
- # The HTTP request method as a lowercase symbol, such as <tt>:get</tt>.
+ # The HTTP request \method as a lowercase symbol, such as <tt>:get</tt>.
# Note, HEAD is returned as <tt>:get</tt> since the two are functionally
# equivalent from the application's perspective.
def method
@@ -59,19 +59,21 @@ module ActionController
request_method == :delete
end
- # Is this a HEAD request? <tt>request.method</tt> sees HEAD as <tt>:get</tt>,
- # so check the HTTP method directly.
+ # Is this a HEAD request? Since <tt>request.method</tt> sees HEAD as <tt>:get</tt>,
+ # this \method checks the actual HTTP \method directly.
def head?
request_method == :head
end
# Provides access to the request's HTTP headers, for example:
- # request.headers["Content-Type"] # => "text/plain"
+ #
+ # request.headers["Content-Type"] # => "text/plain"
def headers
ActionController::Http::Headers.new(@env)
end
memoize :headers
+ # Returns the content length of the request as an integer.
def content_length
@env['CONTENT_LENGTH'].to_i
end
@@ -79,14 +81,14 @@ module ActionController
# The MIME type of the HTTP request, such as Mime::XML.
#
- # For backward compatibility, the post format is extracted from the
+ # For backward compatibility, the post \format is extracted from the
# X-Post-Data-Format HTTP header if present.
def content_type
Mime::Type.lookup(content_type_without_parameters)
end
memoize :content_type
- # Returns the accepted MIME type for the request
+ # Returns the accepted MIME type for the request.
def accepts
header = @env['HTTP_ACCEPT'].to_s.strip
@@ -123,7 +125,7 @@ module ActionController
not_modified?(response.last_modified) || etag_matches?(response.etag)
end
- # Returns the Mime type for the format used in the request.
+ # Returns the Mime type for the \format used in the request.
#
# GET /posts/5.xml | request.format => Mime::XML
# GET /posts/5.xhtml | request.format => Mime::HTML
@@ -142,8 +144,8 @@ module ActionController
end
- # Sets the format by string extension, which can be used to force custom formats that are not controlled by the extension.
- # Example:
+ # Sets the \format by string extension, which can be used to force custom formats
+ # that are not controlled by the extension.
#
# class ApplicationController < ActionController::Base
# before_filter :adjust_format_for_iphone
@@ -159,7 +161,7 @@ module ActionController
end
# Returns a symbolized version of the <tt>:format</tt> parameter of the request.
- # If no format is given it returns <tt>:js</tt>for AJAX requests and <tt>:html</tt>
+ # If no \format is given it returns <tt>:js</tt>for Ajax requests and <tt>:html</tt>
# otherwise.
def template_format
parameter_format = parameters[:format]
@@ -190,7 +192,7 @@ module ActionController
# the right-hand-side of X-Forwarded-For
TRUSTED_PROXIES = /^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i
- # Determine originating IP address. REMOTE_ADDR is the standard
+ # Determines originating IP address. REMOTE_ADDR is the standard
# but will fail if the user is behind a proxy. HTTP_CLIENT_IP and/or
# HTTP_X_FORWARDED_FOR are set by proxies so check for these if
# REMOTE_ADDR is a proxy. HTTP_X_FORWARDED_FOR may be a comma-
@@ -237,13 +239,13 @@ EOM
memoize :server_software
- # Returns the complete URL used for this request
+ # Returns the complete URL used for this request.
def url
protocol + host_with_port + request_uri
end
memoize :url
- # Return 'https://' if this is an SSL request and 'http://' otherwise.
+ # Returns 'https://' if this is an SSL request and 'http://' otherwise.
def protocol
ssl? ? 'https://' : 'http://'
end
@@ -254,6 +256,7 @@ EOM
@env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https'
end
+ # Returns the \host for this request, such as "example.com".
def raw_host_with_port
if forwarded = env["HTTP_X_FORWARDED_HOST"]
forwarded.split(/,\s?/).last
@@ -268,8 +271,8 @@ EOM
end
memoize :host
- # Returns a host:port string for this request, such as example.com or
- # example.com:8080.
+ # Returns a \host:\port string for this request, such as "example.com" or
+ # "example.com:8080".
def host_with_port
"#{host}#{port_string}"
end
@@ -285,7 +288,7 @@ EOM
end
memoize :port
- # Returns the standard port number for this request's protocol
+ # Returns the standard \port number for this request's protocol.
def standard_port
case protocol
when 'https://' then 443
@@ -293,13 +296,13 @@ EOM
end
end
- # Returns a port suffix like ":8080" if the port number of this request
- # is not the default HTTP port 80 or HTTPS port 443.
+ # Returns a \port suffix like ":8080" if the \port number of this request
+ # is not the default HTTP \port 80 or HTTPS \port 443.
def port_string
port == standard_port ? '' : ":#{port}"
end
- # Returns the domain part of a host, such as rubyonrails.org in "www.rubyonrails.org". You can specify
+ # Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify
# a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
def domain(tld_length = 1)
return nil unless named_host?(host)
@@ -307,8 +310,9 @@ EOM
host.split('.').last(1 + tld_length).join('.')
end
- # Returns all the subdomains as an array, so ["dev", "www"] would be returned for "dev.www.rubyonrails.org".
- # You can specify a different <tt>tld_length</tt>, such as 2 to catch ["www"] instead of ["www", "rubyonrails"]
+ # Returns all the \subdomains as an array, so <tt>["dev", "www"]</tt> would be
+ # returned for "dev.www.rubyonrails.org". You can specify a different <tt>tld_length</tt>,
+ # such as 2 to catch <tt>["www"]</tt> instead of <tt>["www", "rubyonrails"]</tt>
# in "www.rubyonrails.co.uk".
def subdomains(tld_length = 1)
return [] unless named_host?(host)
@@ -316,7 +320,7 @@ EOM
parts[0..-(tld_length+2)]
end
- # Return the query string, accounting for server idiosyncrasies.
+ # Returns the query string, accounting for server idiosyncrasies.
def query_string
if uri = @env['REQUEST_URI']
uri.split('?', 2)[1] || ''
@@ -326,7 +330,7 @@ EOM
end
memoize :query_string
- # Return the request URI, accounting for server idiosyncrasies.
+ # Returns the request URI, accounting for server idiosyncrasies.
# WEBrick includes the full URL. IIS leaves REQUEST_URI blank.
def request_uri
if uri = @env['REQUEST_URI']
@@ -352,7 +356,8 @@ EOM
end
memoize :request_uri
- # Returns the interpreted path to requested resource after all the installation directory of this application was taken into account
+ # Returns the interpreted \path to requested resource after all the installation
+ # directory of this application was taken into account.
def path
path = (uri = request_uri) ? uri.split('?').first.to_s : ''
@@ -362,7 +367,7 @@ EOM
end
memoize :path
- # Read the request body. This is useful for web services that need to
+ # Read the request \body. This is useful for web services that need to
# work with raw requests directly.
def raw_post
unless env.include? 'RAW_POST_DATA'
@@ -372,7 +377,7 @@ EOM
env['RAW_POST_DATA']
end
- # Returns both GET and POST parameters in a single hash.
+ # Returns both GET and POST \parameters in a single hash.
def parameters
@parameters ||= request_parameters.merge(query_parameters).update(path_parameters).with_indifferent_access
end
@@ -382,17 +387,17 @@ EOM
@symbolized_path_parameters = @parameters = nil
end
- # The same as <tt>path_parameters</tt> with explicitly symbolized keys
+ # The same as <tt>path_parameters</tt> with explicitly symbolized keys.
def symbolized_path_parameters
@symbolized_path_parameters ||= path_parameters.symbolize_keys
end
- # Returns a hash with the parameters used to form the path of the request.
- # Returned hash keys are strings. See <tt>symbolized_path_parameters</tt> for symbolized keys.
- #
- # Example:
+ # Returns a hash with the \parameters used to form the \path of the request.
+ # Returned hash keys are strings:
#
# {'action' => 'my_action', 'controller' => 'my_controller'}
+ #
+ # See <tt>symbolized_path_parameters</tt> for symbolized keys.
def path_parameters
@path_parameters ||= {}
end
diff --git a/actionpack/lib/action_controller/rescue.rb b/actionpack/lib/action_controller/rescue.rb
index 1492c4ec61..83c4218af4 100644
--- a/actionpack/lib/action_controller/rescue.rb
+++ b/actionpack/lib/action_controller/rescue.rb
@@ -148,7 +148,7 @@ module ActionController #:nodoc:
end
# Overwrite to implement public exception handling (for requests answering false to <tt>local_request?</tt>). By
- # default will call render_optional_error_file. Override this method to provide more user friendly error messages.s
+ # default will call render_optional_error_file. Override this method to provide more user friendly error messages.
def rescue_action_in_public(exception) #:doc:
render_optional_error_file response_code_for_rescue(exception)
end
diff --git a/actionpack/lib/action_controller/resources.rb b/actionpack/lib/action_controller/resources.rb
index 31710caccb..872b0dab3d 100644
--- a/actionpack/lib/action_controller/resources.rb
+++ b/actionpack/lib/action_controller/resources.rb
@@ -1,23 +1,23 @@
module ActionController
# == Overview
#
- # ActionController::Resources are a way of defining RESTful resources. A RESTful resource, in basic terms,
+ # ActionController::Resources are a way of defining RESTful \resources. A RESTful \resource, in basic terms,
# is something that can be pointed at and it will respond with a representation of the data requested.
# In real terms this could mean a user with a browser requests an HTML page, or that a desktop application
# requests XML data.
#
# RESTful design is based on the assumption that there are four generic verbs that a user of an
- # application can request from a resource (the noun).
+ # application can request from a \resource (the noun).
#
- # Resources can be requested using four basic HTTP verbs (GET, POST, PUT, DELETE), the method used
+ # \Resources can be requested using four basic HTTP verbs (GET, POST, PUT, DELETE), the method used
# denotes the type of action that should take place.
#
# === The Different Methods and their Usage
#
- # [+GET+] Requests for a resource, no saving or editing of a resource should occur in a GET request
- # [+POST+] Creation of resources
- # [+PUT+] Editing of attributes on a resource
- # [+DELETE+] Deletion of a resource
+ # * GET - Requests for a \resource, no saving or editing of a \resource should occur in a GET request.
+ # * POST - Creation of \resources.
+ # * PUT - Editing of attributes on a \resource.
+ # * DELETE - Deletion of a \resource.
#
# === Examples
#
@@ -156,7 +156,7 @@ module ActionController
end
# Creates named routes for implementing verb-oriented controllers
- # for a collection resource.
+ # for a collection \resource.
#
# For example:
#
@@ -252,20 +252,20 @@ module ActionController
# an array of any of the previous, or <tt>:any</tt> if the method does not matter.
# These routes map to a URL like /messages/rss, with a route of +rss_messages_url+.
# * <tt>:member</tt> - Same as <tt>:collection</tt>, but for actions that operate on a specific member.
- # * <tt>:new</tt> - Same as <tt>:collection</tt>, but for actions that operate on the new resource action.
+ # * <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>: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:
+ # * <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'
# map.resources :products, :as => 'productos' do |product|
# # product_reviews_path(product) == '/productos/1234/comentarios'
# product.resources :product_reviews, :as => 'comentarios'
# end
#
- # * <tt>:has_one</tt> - Specify nested resources, this is a shorthand for mapping singleton resources beneath the current.
- # * <tt>:has_many</tt> - Same has <tt>:has_one</tt>, but for plural resources.
+ # * <tt>:has_one</tt> - Specify nested \resources, this is a shorthand for mapping singleton \resources beneath the current.
+ # * <tt>:has_many</tt> - Same has <tt>:has_one</tt>, but for plural \resources.
#
# You may directly specify the routing association with +has_one+ and +has_many+ like:
#
@@ -288,18 +288,18 @@ module ActionController
#
# * <tt>:path_prefix</tt> - Set a prefix to the routes with required route variables.
#
- # Weblog comments usually belong to a post, so you might use resources like:
+ # Weblog comments usually belong to a post, so you might use +resources+ like:
#
# map.resources :articles
# map.resources :comments, :path_prefix => '/articles/:article_id'
#
- # You can nest resources calls to set this automatically:
+ # You can nest +resources+ calls to set this automatically:
#
# map.resources :articles do |article|
# article.resources :comments
# end
#
- # The comment resources work the same, but must now include a value for <tt>:article_id</tt>.
+ # The comment \resources work the same, but must now include a value for <tt>:article_id</tt>.
#
# article_comments_url(@article)
# article_comment_url(@article, @comment)
@@ -317,13 +317,13 @@ module ActionController
# map.resources :tags, :path_prefix => '/books/:book_id', :name_prefix => 'book_'
# map.resources :tags, :path_prefix => '/toys/:toy_id', :name_prefix => 'toy_'
#
- # You may also use <tt>:name_prefix</tt> to override the generic named routes in a nested resource:
+ # You may also use <tt>:name_prefix</tt> to override the generic named routes in a nested \resource:
#
# map.resources :articles do |article|
# article.resources :comments, :name_prefix => nil
# end
#
- # This will yield named resources like so:
+ # This will yield named \resources like so:
#
# comments_url(@article)
# comment_url(@article, @comment)
@@ -385,28 +385,28 @@ module ActionController
#
# The +resources+ method sets HTTP method restrictions on the routes it generates. For example, making an
# HTTP POST on <tt>new_message_url</tt> will raise a RoutingError exception. The default route in
- # <tt>config/routes.rb</tt> overrides this and allows invalid HTTP methods for resource routes.
+ # <tt>config/routes.rb</tt> overrides this and allows invalid HTTP methods for \resource routes.
def resources(*entities, &block)
options = entities.extract_options!
entities.each { |entity| map_resource(entity, options.dup, &block) }
end
- # Creates named routes for implementing verb-oriented controllers for a singleton resource.
- # A singleton resource is global to its current context. For unnested singleton resources,
- # the resource is global to the current user visiting the application, such as a user's
- # /account profile. For nested singleton resources, the resource is global to its parent
- # resource, such as a <tt>projects</tt> resource that <tt>has_one :project_manager</tt>.
- # The <tt>project_manager</tt> should be mapped as a singleton resource under <tt>projects</tt>:
+ # Creates named routes for implementing verb-oriented controllers for a singleton \resource.
+ # A singleton \resource is global to its current context. For unnested singleton \resources,
+ # the \resource is global to the current user visiting the application, such as a user's
+ # <tt>/account</tt> profile. For nested singleton \resources, the \resource is global to its parent
+ # \resource, such as a <tt>projects</tt> \resource that <tt>has_one :project_manager</tt>.
+ # The <tt>project_manager</tt> should be mapped as a singleton \resource under <tt>projects</tt>:
#
# map.resources :projects do |project|
# project.resource :project_manager
# end
#
- # See map.resources for general conventions. These are the main differences:
- # * A singular name is given to map.resource. The default controller name is still taken from the plural name.
+ # See +resources+ for general conventions. These are the main differences:
+ # * A singular name is given to <tt>map.resource</tt>. The default controller name is still taken from the plural name.
# * To specify a custom plural name, use the <tt>:plural</tt> option. There is no <tt>:singular</tt> option.
- # * No default index route is created for the singleton resource controller.
- # * When nesting singleton resources, only the singular name is used as the path prefix (example: 'account/messages/1')
+ # * No default index route is created for the singleton \resource controller.
+ # * When nesting singleton \resources, only the singular name is used as the path prefix (example: 'account/messages/1')
#
# For example:
#
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index e8ca02d760..e5777b71d7 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -155,10 +155,10 @@ module ActionView
# Creates a file upload field. If you are using file uploads then you will also need
# to set the multipart option for the form tag:
#
- # <%= form_tag { :action => "post" }, { :multipart => true } %>
+ # <% form_tag '/upload', :multipart => true do %>
# <label for="file">File to Upload</label> <%= file_field_tag "file" %>
# <%= submit_tag %>
- # <%= end_form_tag %>
+ # <% end %>
#
# The specified URL will then be passed a File object containing the selected file, or if the field
# was left blank, a StringIO object.
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index 2f08583b16..ff41a6d417 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -614,7 +614,7 @@ module ActionView
# Example:
#
# # Generates:
- # # new Element.insert("list", { bottom: <li>Some item</li>" });
+ # # new Element.insert("list", { bottom: "<li>Some item</li>" });
# # new Effect.Highlight("list");
# # ["status-indicator", "cancel-link"].each(Element.hide);
# update_page do |page|
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 06f8226229..ab1fdc80bc 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -507,7 +507,7 @@ module ActionView
# @items = [1,2,3,4]
# <% @items.each do |item| %>
# <div style="background-color:<%= cycle("red","white","blue") %>">
- # <span style="background-color:<%= current_cycle %><%= item %></span>
+ # <span style="background-color:<%= current_cycle %>"><%= item %></span>
# </div>
# <% end %>
def current_cycle(name = "default")
diff --git a/activemodel/lib/active_model/validations/uniqueness.rb b/activemodel/lib/active_model/validations/uniqueness.rb
index 5075951636..593d2cfd54 100644
--- a/activemodel/lib/active_model/validations/uniqueness.rb
+++ b/activemodel/lib/active_model/validations/uniqueness.rb
@@ -25,7 +25,7 @@ module ActiveModel
# Configuration options:
# * <tt>:message</tt> - Specifies a custom error message (default is: "has already been taken")
# * <tt>:scope</tt> - One or more columns by which to limit the scope of the uniqueness constraint.
- # * <tt>:case_sensitive</tt> - Looks for an exact match. Ignored by non-text columns (+false+ by default).
+ # * <tt>:case_sensitive</tt> - Looks for an exact match. Ignored by non-text columns (+true+ by default).
# * <tt>:allow_nil</tt> - If set to +true+, skips this validation if the attribute is +nil+ (default is: +false+)
# * <tt>:allow_blank</tt> - If set to +true+, skips this validation if the attribute is blank (default is: +false+)
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should
@@ -101,4 +101,4 @@ module ActiveModel
end
end
end
-end \ No newline at end of file
+end
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index dccd9abf31..6405071354 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -660,8 +660,8 @@ module ActiveRecord
#
# === Example
#
- # A Firm class declares <tt>has_many :clients</tt>, which will add:
- # * <tt>Firm#clients</tt> (similar to <tt>Clients.find :all, :conditions => "firm_id = #{id}"</tt>)
+ # Example: A Firm class declares <tt>has_many :clients</tt>, which will add:
+ # * <tt>Firm#clients</tt> (similar to <tt>Clients.find :all, :conditions => ["firm_id = ?", id]</tt>)
# * <tt>Firm#clients<<</tt>
# * <tt>Firm#clients.delete</tt>
# * <tt>Firm#clients=</tt>
@@ -1223,12 +1223,11 @@ module ActiveRecord
end
private
- # Generate a join table name from two provided tables names.
- # The order of names in join name is determined by lexical precedence.
- # join_table_name("members", "clubs")
- # => "clubs_members"
- # join_table_name("members", "special_clubs")
- # => "members_special_clubs"
+ # Generates a join table name from two provided table names.
+ # The names in the join table namesme end up in lexicographic order.
+ #
+ # join_table_name("members", "clubs") # => "clubs_members"
+ # join_table_name("members", "special_clubs") # => "members_special_clubs"
def join_table_name(first_table_name, second_table_name)
if first_table_name < second_table_name
join_table = "#{first_table_name}_#{second_table_name}"
diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb
index 5092ccc1dc..168443e092 100644
--- a/activerecord/lib/active_record/associations/association_collection.rb
+++ b/activerecord/lib/active_record/associations/association_collection.rb
@@ -2,6 +2,19 @@ require 'set'
module ActiveRecord
module Associations
+ # AssociationCollection is an abstract class that provides common stuff to
+ # ease the implementation of association proxies that represent
+ # collections. See the class hierarchy in AssociationProxy.
+ #
+ # You need to be careful with assumptions regarding the target: The proxy
+ # does not fetch records from the database until it needs them, but new
+ # ones created with +build+ are added to the target. So, the target may be
+ # non-empty and still lack children waiting to be read from the database.
+ # If you look directly to the database you cannot assume that's the entire
+ # collection because new records may have beed added to the target, etc.
+ #
+ # If you need to work on all current children, new and existing records,
+ # +load_target+ and the +loaded+ flag are your friends.
class AssociationCollection < AssociationProxy #:nodoc:
def initialize(owner, reflection)
super
@@ -214,9 +227,16 @@ module ActiveRecord
end
end
- # Returns the size of the collection by executing a SELECT COUNT(*) query if the collection hasn't been loaded and
- # calling collection.size if it has. If it's more likely than not that the collection does have a size larger than zero
- # and you need to fetch that collection afterwards, it'll take one less SELECT query if you use length.
+ # Returns the size of the collection by executing a SELECT COUNT(*)
+ # query if the collection hasn't been loaded, and calling
+ # <tt>collection.size</tt> if it has.
+ #
+ # If the collection has been already loaded +size+ and +length+ are
+ # equivalent. If not and you are going to need the records anyway
+ # +length+ will take one less query. Otherwise +size+ is more efficient.
+ #
+ # This method is abstract in the sense that it relies on
+ # +count_records+, which is a method descendants have to provide.
def size
if @owner.new_record? || (loaded? && !@reflection.options[:uniq])
@target.size
@@ -228,12 +248,18 @@ module ActiveRecord
end
end
- # Returns the size of the collection by loading it and calling size on the array. If you want to use this method to check
- # whether the collection is empty, use collection.length.zero? instead of collection.empty?
+ # Returns the size of the collection calling +size+ on the target.
+ #
+ # If the collection has been already loaded +length+ and +size+ are
+ # equivalent. If not and you are going to need the records anyway this
+ # method will take one less query. Otherwise +size+ is more efficient.
def length
load_target.size
end
+ # Equivalent to <tt>collection.size.zero?</tt>. If the collection has
+ # not been already loaded and you are going to fetch the records anyway
+ # it is better to check <tt>collection.length.zero?</tt>.
def empty?
size.zero?
end
diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb
index 5427681f3c..acdcd14ec8 100644
--- a/activerecord/lib/active_record/associations/association_proxy.rb
+++ b/activerecord/lib/active_record/associations/association_proxy.rb
@@ -39,7 +39,7 @@ module ActiveRecord
# though the object behind <tt>blog.posts</tt> is not an Array, but an
# ActiveRecord::Associations::HasManyAssociation.
#
- # The <tt>@target</tt> object is not loaded until needed. For example,
+ # The <tt>@target</tt> object is not \loaded until needed. For example,
#
# blog.posts.count
#
@@ -57,76 +57,100 @@ module ActiveRecord
reset
end
+ # Returns the owner of the proxy.
def proxy_owner
@owner
end
+ # Returns the reflection object that represents the association handled
+ # by the proxy.
def proxy_reflection
@reflection
end
+ # Returns the \target of the proxy, same as +target+.
def proxy_target
@target
end
+ # Does the proxy or its \target respond to +symbol+?
def respond_to?(*args)
proxy_respond_to?(*args) || (load_target && @target.respond_to?(*args))
end
- # Explicitly proxy === because the instance method removal above
- # doesn't catch it.
+ # Forwards <tt>===</tt> explicitly to the \target because the instance method
+ # removal above doesn't catch it. Loads the \target if needed.
def ===(other)
load_target
other === @target
end
+ # Returns the name of the table of the related class:
+ #
+ # post.comments.aliased_table_name # => "comments"
+ #
def aliased_table_name
@reflection.klass.table_name
end
+ # Returns the SQL string that corresponds to the <tt>:conditions</tt>
+ # option of the macro, if given, or +nil+ otherwise.
def conditions
@conditions ||= interpolate_sql(@reflection.sanitized_conditions) if @reflection.sanitized_conditions
end
alias :sql_conditions :conditions
+ # Resets the \loaded flag to +false+ and sets the \target to +nil+.
def reset
@loaded = false
@target = nil
end
+ # Reloads the \target and returns +self+ on success.
def reload
reset
load_target
self unless @target.nil?
end
+ # Has the \target been already \loaded?
def loaded?
@loaded
end
+ # Asserts the \target has been loaded setting the \loaded flag to +true+.
def loaded
@loaded = true
end
+ # Returns the target of this proxy, same as +proxy_target+.
def target
@target
end
+ # Sets the target of this proxy to <tt>\target</tt>, and the \loaded flag to +true+.
def target=(target)
@target = target
loaded
end
+ # Forwards the call to the target. Loads the \target if needed.
def inspect
load_target
@target.inspect
end
protected
+ # Does the association have a <tt>:dependent</tt> option?
def dependent?
@reflection.options[:dependent]
end
+ # Returns a string with the IDs of +records+ joined with a comma, quoted
+ # if needed. The result is ready to be inserted into a SQL IN clause.
+ #
+ # quoted_record_ids(records) # => "23,56,58,67"
+ #
def quoted_record_ids(records)
records.map { |record| record.quoted_id }.join(',')
end
@@ -135,10 +159,13 @@ module ActiveRecord
@owner.send(:interpolate_sql, sql, record)
end
+ # Forwards the call to the reflection class.
def sanitize_sql(sql)
@reflection.klass.send(:sanitize_sql, sql)
end
+ # Assigns the ID of the owner to the corresponding foreign key in +record+.
+ # If the association is polymorphic the type of the owner is also set.
def set_belongs_to_association_for(record)
if @reflection.options[:as]
record["#{@reflection.options[:as]}_id"] = @owner.id unless @owner.new_record?
@@ -148,6 +175,7 @@ module ActiveRecord
end
end
+ # Merges into +options+ the ones coming from the reflection.
def merge_options_from_reflection!(options)
options.reverse_merge!(
:group => @reflection.options[:group],
@@ -160,11 +188,13 @@ module ActiveRecord
)
end
+ # Forwards +with_scope+ to the reflection.
def with_scope(*args, &block)
@reflection.klass.send :with_scope, *args, &block
end
private
+ # Forwards any missing method call to the \target.
def method_missing(method, *args)
if load_target
if block_given?
@@ -175,16 +205,16 @@ module ActiveRecord
end
end
- # Loads the target if needed and returns it.
+ # Loads the \target if needed and returns it.
#
# This method is abstract in the sense that it relies on +find_target+,
# which is expected to be provided by descendants.
#
- # If the target is already loaded it is just returned. Thus, you can call
- # +load_target+ unconditionally to get the target.
+ # If the \target is already \loaded it is just returned. Thus, you can call
+ # +load_target+ unconditionally to get the \target.
#
# ActiveRecord::RecordNotFound is rescued within the method, and it is
- # not reraised. The proxy is reset and +nil+ is the return value.
+ # not reraised. The proxy is \reset and +nil+ is the return value.
def load_target
return nil unless defined?(@loaded)
@@ -198,12 +228,17 @@ module ActiveRecord
reset
end
- # Can be overwritten by associations that might have the foreign key available for an association without
- # having the object itself (and still being a new record). Currently, only belongs_to presents this scenario.
+ # Can be overwritten by associations that might have the foreign key
+ # available for an association without having the object itself (and
+ # still being a new record). Currently, only +belongs_to+ presents
+ # this scenario (both vanilla and polymorphic).
def foreign_key_present
false
end
+ # Raises ActiveRecord::AssociationTypeMismatch unless +record+ is of
+ # the kind of the class of the associated objects. Meant to be used as
+ # a sanity check when you are about to assign an associated record.
def raise_on_type_mismatch(record)
unless record.is_a?(@reflection.klass)
message = "#{@reflection.class_name}(##{@reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"
@@ -211,11 +246,13 @@ module ActiveRecord
end
end
- # Array#flatten has problems with recursive arrays. Going one level deeper solves the majority of the problems.
+ # Array#flatten has problems with recursive arrays. Going one level
+ # deeper solves the majority of the problems.
def flatten_deeper(array)
array.collect { |element| (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element }.flatten
end
+ # Returns the ID of the owner, quoted if needed.
def owner_quoted_id
@owner.quoted_id
end
diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb
index 1838021d40..dda22668c6 100644
--- a/activerecord/lib/active_record/associations/has_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_association.rb
@@ -1,5 +1,9 @@
module ActiveRecord
module Associations
+ # This is the proxy that handles a has many association.
+ #
+ # If the association has a <tt>:through</tt> option further specialization
+ # is provided by its child HasManyThroughAssociation.
class HasManyAssociation < AssociationCollection #:nodoc:
protected
def owner_quoted_id
@@ -10,6 +14,16 @@ module ActiveRecord
end
end
+ # Returns the number of records in this collection.
+ #
+ # If the association has a counter cache it gets that value. Otherwise
+ # a count via SQL is performed, bounded to <tt>:limit</tt> if there's one.
+ # That does not depend on whether the collection has already been loaded
+ # or not. The +size+ method is the one that takes the loaded flag into
+ # account and delegates to +count_records+ if needed.
+ #
+ # If the collection is empty the target is set to an empty array and
+ # the loaded flag is set to true as well.
def count_records
count = if has_cached_counter?
@owner.send(:read_attribute, cached_counter_attribute_name)
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 2367277c03..3419aad580 100644..100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -500,7 +500,7 @@ module ActiveRecord #:nodoc:
# * <tt>:include</tt> - Names associations that should be loaded alongside. The symbols named refer
# to already defined associations. See eager loading under Associations.
# * <tt>:select</tt> - By default, this is "*" as in "SELECT * FROM", but can be changed if you, for example, want to do a join but not
- # include the joined columns.
+ # include the joined columns. Takes a string with the SELECT SQL fragment (e.g. "id, name").
# * <tt>:from</tt> - By default, this is the table name of the class, but can be changed to an alternate table name (or even the name
# of a database view).
# * <tt>:readonly</tt> - Mark the returned records read-only so they cannot be saved or updated.
@@ -745,13 +745,15 @@ module ActiveRecord #:nodoc:
end
# Updates all records with details given if they match a set of conditions supplied, limits and order can
- # also be supplied.
+ # also be supplied. This method constructs a single SQL UPDATE statement and sends it straight to the
+ # database. It does not instantiate the involved models and it does not trigger Active Record callbacks.
#
# ==== Attributes
#
- # * +updates+ - A String of column and value pairs that will be set on any records that match conditions.
+ # * +updates+ - A string of column and value pairs that will be set on any records that match conditions.
+ # What goes into the SET clause.
# * +conditions+ - An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro for more info.
- # * +options+ - Additional options are <tt>:limit</tt> and/or <tt>:order</tt>, see the examples for usage.
+ # * +options+ - Additional options are <tt>:limit</tt> and <tt>:order</tt>, see the examples for usage.
#
# ==== Examples
#
@@ -773,8 +775,8 @@ module ActiveRecord #:nodoc:
connection.update(sql, "#{name} Update")
end
- # Destroys the records matching +conditions+ by instantiating each record and calling the destroy method.
- # This means at least 2*N database queries to destroy N records, so avoid destroy_all if you are deleting
+ # Destroys the records matching +conditions+ by instantiating each record and calling their +destroy+ method.
+ # This means at least 2*N database queries to destroy N records, so avoid +destroy_all+ if you are deleting
# many records. If you want to simply delete records without worrying about dependent associations or
# callbacks, use the much faster +delete_all+ method instead.
#
@@ -793,8 +795,9 @@ module ActiveRecord #:nodoc:
end
# Deletes the records matching +conditions+ without instantiating the records first, and hence not
- # calling the destroy method and invoking callbacks. This is a single SQL query, much more efficient
- # than destroy_all.
+ # calling the +destroy+ method nor invoking callbacks. This is a single SQL DELETE statement that
+ # goes straight to the database, much more efficient than +destroy_all+. Careful with relations
+ # though, in particular <tt>:dependent</tt> is not taken into account.
#
# ==== Attributes
#
@@ -804,8 +807,8 @@ module ActiveRecord #:nodoc:
#
# Post.delete_all "person_id = 5 AND (category = 'Something' OR category = 'Else')"
#
- # This deletes the affected posts all at once with a single DELETE query. If you need to destroy dependent
- # associations or call your before_ or after_destroy callbacks, use the +destroy_all+ method instead.
+ # This deletes the affected posts all at once with a single DELETE statement. If you need to destroy dependent
+ # associations or call your <tt>before_*</tt> or +after_destroy+ callbacks, use the +destroy_all+ method instead.
def delete_all(conditions = nil)
sql = "DELETE FROM #{quoted_table_name} "
add_conditions!(sql, conditions, scope(:find))
@@ -2248,20 +2251,40 @@ module ActiveRecord #:nodoc:
defined?(@new_record) && @new_record
end
- # * No record exists: Creates a new record with values matching those of the object attributes.
- # * A record does exist: Updates the record with values matching those of the object attributes.
+ # :call-seq:
+ # save(perform_validation = true)
#
- # Note: If your model specifies any validations then the method declaration dynamically
- # changes to:
- # save(perform_validation=true)
- # Calling save(false) saves the model without running validations.
- # See ActiveRecord::Validations for more information.
+ # Saves the model.
+ #
+ # If the model is new a record gets created in the database, otherwise
+ # the existing record gets updated.
+ #
+ # If +perform_validation+ is true validations run. If any of them fail
+ # the action is cancelled and +save+ returns +false+. If the flag is
+ # false validations are bypassed altogether. See
+ # ActiveRecord::Validations for more information.
+ #
+ # There's a series of callbacks associated with +save+. If any of the
+ # <tt>before_*</tt> callbacks return +false+ the action is cancelled and
+ # +save+ returns +false+. See ActiveRecord::Callbacks for further
+ # details.
def save
create_or_update
end
- # Attempts to save the record, but instead of just returning false if it couldn't happen, it raises a
- # RecordNotSaved exception
+ # Saves the model.
+ #
+ # If the model is new a record gets created in the database, otherwise
+ # the existing record gets updated.
+ #
+ # With <tt>save!</tt> validations always run. If any of them fail
+ # ActiveRecord::RecordInvalid gets raised. See ActiveRecord::Validations
+ # for more information.
+ #
+ # There's a series of callbacks associated with <tt>save!</tt>. If any of
+ # the <tt>before_*</tt> callbacks return +false+ the action is cancelled
+ # and <tt>save!</tt> raises ActiveRecord::RecordNotSaved. See
+ # ActiveRecord::Callbacks for further details.
def save!
create_or_update || raise(RecordNotSaved)
end
diff --git a/activerecord/lib/active_record/calculations.rb b/activerecord/lib/active_record/calculations.rb
index 0325a8f8ca..a675af4787 100644
--- a/activerecord/lib/active_record/calculations.rb
+++ b/activerecord/lib/active_record/calculations.rb
@@ -14,7 +14,7 @@ module ActiveRecord
#
# The third approach, count using options, accepts an option hash as the only parameter. The options are:
#
- # * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro.
+ # * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro to ActiveRecord::Base.
# * <tt>:joins</tt>: Either an SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id" (rarely needed)
# or named associations in the same form used for the <tt>:include</tt> option, which will perform an INNER JOIN on the associated table(s).
# If the value is a string, then the records will be returned read-only since they will have attributes that do not correspond to the table's columns.
@@ -98,7 +98,7 @@ module ActiveRecord
# end
#
# Options:
- # * <tt>:conditions</tt> - An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro.
+ # * <tt>:conditions</tt> - An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro to ActiveRecord::Base.
# * <tt>:include</tt>: Eager loading, see Associations for details. Since calculations don't load anything, the purpose of this is to access fields on joined tables in your conditions, order, or group clauses.
# * <tt>:joins</tt> - An SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id". (Rarely needed).
# The records will be returned read-only since they will have attributes that do not correspond to the table's columns.
diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb
index eec531c514..dd7ae51096 100644
--- a/activerecord/lib/active_record/callbacks.rb
+++ b/activerecord/lib/active_record/callbacks.rb
@@ -3,7 +3,7 @@ require 'observer'
module ActiveRecord
# Callbacks are hooks into the lifecycle of an Active Record object that allow you to trigger logic
# before or after an alteration of the object state. This can be used to make sure that associated and
- # dependent objects are deleted when destroy is called (by overwriting +before_destroy+) or to massage attributes
+ # dependent objects are deleted when +destroy+ is called (by overwriting +before_destroy+) or to massage attributes
# before they're validated (by overwriting +before_validation+). As an example of the callbacks initiated, consider
# the <tt>Base#save</tt> call:
#
@@ -161,7 +161,7 @@ module ActiveRecord
# == <tt>before_validation*</tt> returning statements
#
# If the returning value of a +before_validation+ callback can be evaluated to +false+, the process will be aborted and <tt>Base#save</tt> will return +false+.
- # If Base#save! is called it will raise a RecordNotSaved exception.
+ # If Base#save! is called it will raise a ActiveRecord::RecordInvalid exception.
# Nothing will be appended to the errors object.
#
# == Canceling callbacks
@@ -209,6 +209,8 @@ module ActiveRecord
def before_save() end
# Is called _after_ <tt>Base.save</tt> (regardless of whether it's a +create+ or +update+ save).
+ # Note that this callback is still wrapped in the transaction around +save+. For example, if you
+ # invoke an external indexer at this point it won't see the changes in the database.
#
# class Contact < ActiveRecord::Base
# after_save { logger.info( 'New contact saved!' ) }
@@ -226,6 +228,8 @@ module ActiveRecord
def before_create() end
# Is called _after_ <tt>Base.save</tt> on new objects that haven't been saved yet (no record exists).
+ # Note that this callback is still wrapped in the transaction around +save+. For example, if you
+ # invoke an external indexer at this point it won't see the changes in the database.
def after_create() end
def create_with_callbacks #:nodoc:
return false if callback(:before_create) == false
@@ -239,6 +243,8 @@ module ActiveRecord
def before_update() end
# Is called _after_ <tt>Base.save</tt> on existing objects that have a record.
+ # Note that this callback is still wrapped in the transaction around +save+. For example, if you
+ # invoke an external indexer at this point it won't see the changes in the database.
def after_update() end
def update_with_callbacks(*args) #:nodoc:
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index d7e152ed1d..83043c2c22 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -1,10 +1,10 @@
module ActiveRecord
module NamedScope
- # All subclasses of ActiveRecord::Base have two named_scopes:
- # * <tt>all</tt>, which is similar to a <tt>find(:all)</tt> query, and
- # * <tt>scoped</tt>, which allows for the creation of anonymous scopes, on the fly: <tt>Shirt.scoped(:conditions => {:color => 'red'}).scoped(:include => :washing_instructions)</tt>
+ # All subclasses of ActiveRecord::Base have two named \scopes:
+ # * <tt>all</tt> - which is similar to a <tt>find(:all)</tt> query, and
+ # * <tt>scoped</tt> - which allows for the creation of anonymous \scopes, on the fly: <tt>Shirt.scoped(:conditions => {:color => 'red'}).scoped(:include => :washing_instructions)</tt>
#
- # These anonymous scopes tend to be useful when procedurally generating complex queries, where passing
+ # These anonymous \scopes tend to be useful when procedurally generating complex queries, where passing
# intermediate values (scopes) around as first-class objects is convenient.
def self.included(base)
base.class_eval do
@@ -26,20 +26,20 @@ module ActiveRecord
# named_scope :dry_clean_only, :joins => :washing_instructions, :conditions => ['washing_instructions.dry_clean_only = ?', true]
# end
#
- # The above calls to <tt>named_scope</tt> define class methods <tt>Shirt.red</tt> and <tt>Shirt.dry_clean_only</tt>. <tt>Shirt.red</tt>,
+ # The above calls to <tt>named_scope</tt> define class methods Shirt.red and Shirt.dry_clean_only. Shirt.red,
# in effect, represents the query <tt>Shirt.find(:all, :conditions => {:color => 'red'})</tt>.
#
- # Unlike Shirt.find(...), however, the object returned by <tt>Shirt.red</tt> is not an Array; it resembles the association object
+ # Unlike <tt>Shirt.find(...)</tt>, however, the object returned by Shirt.red is not an Array; it resembles the association object
# constructed by a <tt>has_many</tt> declaration. For instance, you can invoke <tt>Shirt.red.find(:first)</tt>, <tt>Shirt.red.count</tt>,
# <tt>Shirt.red.find(:all, :conditions => {:size => 'small'})</tt>. Also, just
- # as with the association objects, name scopes acts like an Array, implementing Enumerable; <tt>Shirt.red.each(&block)</tt>,
- # <tt>Shirt.red.first</tt>, and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if Shirt.red really were an Array.
+ # as with the association objects, named \scopes act like an Array, implementing Enumerable; <tt>Shirt.red.each(&block)</tt>,
+ # <tt>Shirt.red.first</tt>, and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if Shirt.red really was an Array.
#
- # These named scopes are composable. For instance, <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are both red and dry clean only.
+ # These named \scopes are composable. For instance, <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are both red and dry clean only.
# Nested finds and calculations also work with these compositions: <tt>Shirt.red.dry_clean_only.count</tt> returns the number of garments
# for which these criteria obtain. Similarly with <tt>Shirt.red.dry_clean_only.average(:thread_count)</tt>.
#
- # All scopes are available as class methods on the ActiveRecord::Base descendent upon which the scopes were defined. But they are also available to
+ # All \scopes are available as class methods on the ActiveRecord::Base descendent upon which the \scopes were defined. But they are also available to
# <tt>has_many</tt> associations. If,
#
# class Person < ActiveRecord::Base
@@ -49,7 +49,7 @@ module ActiveRecord
# then <tt>elton.shirts.red.dry_clean_only</tt> will return all of Elton's red, dry clean
# only shirts.
#
- # Named scopes can also be procedural.
+ # Named \scopes can also be procedural:
#
# class Shirt < ActiveRecord::Base
# named_scope :colored, lambda { |color|
@@ -59,7 +59,7 @@ module ActiveRecord
#
# In this example, <tt>Shirt.colored('puce')</tt> finds all puce shirts.
#
- # Named scopes can also have extensions, just as with <tt>has_many</tt> declarations:
+ # Named \scopes can also have extensions, just as with <tt>has_many</tt> declarations:
#
# class Shirt < ActiveRecord::Base
# named_scope :red, :conditions => {:color => 'red'} do
@@ -70,7 +70,7 @@ module ActiveRecord
# end
#
#
- # For testing complex named scopes, you can examine the scoping options using the
+ # For testing complex named \scopes, you can examine the scoping options using the
# <tt>proxy_options</tt> method on the proxy itself.
#
# class Shirt < ActiveRecord::Base
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 81462a2917..970da701c7 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -64,7 +64,7 @@ module ActiveRecord
#
# Both Base#save and Base#destroy come wrapped in a transaction that ensures that whatever you do in validations or callbacks
# will happen under the protected cover of a transaction. So you can use validations to check for values that the transaction
- # depends on or you can raise exceptions in the callbacks to rollback.
+ # depends on or you can raise exceptions in the callbacks to rollback, including <tt>after_*</tt> callbacks.
#
# == Exception handling and rolling back
#
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index 9941b752cb..577e30ec86 100644
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -619,7 +619,7 @@ module ActiveRecord
# Configuration options:
# * <tt>:message</tt> - Specifies a custom error message (default is: "has already been taken").
# * <tt>:scope</tt> - One or more columns by which to limit the scope of the uniqueness constraint.
- # * <tt>:case_sensitive</tt> - Looks for an exact match. Ignored by non-text columns (+false+ by default).
+ # * <tt>:case_sensitive</tt> - Looks for an exact match. Ignored by non-text columns (+true+ by default).
# * <tt>:allow_nil</tt> - If set to true, skips this validation if the attribute is +nil+ (default is +false+).
# * <tt>:allow_blank</tt> - If set to true, skips this validation if the attribute is blank (default is +false+).
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index 749cc59284..d966062c7f 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -54,7 +54,7 @@ module ActiveResource
#
# Since simple CRUD/lifecycle methods can't accomplish every task, Active Resource also supports
# defining your own custom REST methods. To invoke them, Active Resource provides the <tt>get</tt>,
- # <tt>post</tt>, <tt>put</tt> and <tt>delete</tt> methods where you can specify a custom REST method
+ # <tt>post</tt>, <tt>put</tt> and <tt>\delete</tt> methods where you can specify a custom REST method
# name to invoke.
#
# # POST to the custom 'register' REST method, i.e. POST /people/new/register.xml.
@@ -129,13 +129,19 @@ module ActiveResource
#
# <tt>404</tt> is just one of the HTTP error response codes that Active Resource will handle with its own exception. The
# following HTTP response codes will also result in these exceptions:
- #
- # * 200..399 - Valid response, no exception
+ #
+ # * 200..399 - Valid response, no exception (other than 301, 302)
+ # * 301, 302 - ActiveResource::Redirection
+ # * 400 - ActiveResource::BadRequest
+ # * 401 - ActiveResource::UnauthorizedAccess
+ # * 403 - ActiveResource::ForbiddenAccess
# * 404 - ActiveResource::ResourceNotFound
+ # * 405 - ActiveResource::MethodNotAllowed
# * 409 - ActiveResource::ResourceConflict
# * 422 - ActiveResource::ResourceInvalid (rescued by save as validation errors)
# * 401..499 - ActiveResource::ClientError
# * 500..599 - ActiveResource::ServerError
+ # * Other - ActiveResource::ConnectionError
#
# These custom exceptions allow you to deal with resource errors more naturally and with more precision
# rather than returning a general HTTP error. For example:
@@ -175,7 +181,7 @@ module ActiveResource
# === Timeouts
#
# Active Resource relies on HTTP to access RESTful APIs and as such is inherently susceptible to slow or
- # unresponsive servers. In such cases, your Active Resource method calls could timeout. You can control the
+ # unresponsive servers. In such cases, your Active Resource method calls could \timeout. You can control the
# amount of time before Active Resource times out with the +timeout+ variable.
#
# class Person < ActiveResource::Base
@@ -189,7 +195,7 @@ module ActiveResource
# http://en.wikipedia.org/wiki/Fail-fast) rather than cause cascading failures that could incapacitate your
# server.
#
- # When a timeout occurs, an ActiveResource::TimeoutError is raised. You should rescue from
+ # When a \timeout occurs, an ActiveResource::TimeoutError is raised. You should rescue from
# ActiveResource::TimeoutError in your Active Resource method calls.
#
# Internally, Active Resource relies on Ruby's Net::HTTP library to make HTTP requests. Setting +timeout+
@@ -238,7 +244,7 @@ module ActiveResource
end
end
- # Gets the user for REST HTTP authentication.
+ # Gets the \user for REST HTTP authentication.
def user
# Not using superclass_delegating_reader. See +site+ for explanation
if defined?(@user)
@@ -248,13 +254,13 @@ module ActiveResource
end
end
- # Sets the user for REST HTTP authentication.
+ # Sets the \user for REST HTTP authentication.
def user=(user)
@connection = nil
@user = user
end
- # Gets the password for REST HTTP authentication.
+ # Gets the \password for REST HTTP authentication.
def password
# Not using superclass_delegating_reader. See +site+ for explanation
if defined?(@password)
@@ -264,7 +270,7 @@ module ActiveResource
end
end
- # Sets the password for REST HTTP authentication.
+ # Sets the \password for REST HTTP authentication.
def password=(password)
@connection = nil
@password = password
@@ -307,8 +313,8 @@ module ActiveResource
end
end
- # An instance of ActiveResource::Connection that is the base connection to the remote service.
- # The +refresh+ parameter toggles whether or not the connection is refreshed at every request
+ # An instance of ActiveResource::Connection that is the base \connection to the remote service.
+ # The +refresh+ parameter toggles whether or not the \connection is refreshed at every request
# or not (defaults to <tt>false</tt>).
def connection(refresh = false)
if defined?(@connection) || superclass == Object
@@ -332,9 +338,9 @@ module ActiveResource
attr_accessor_with_default(:collection_name) { element_name.pluralize } #:nodoc:
attr_accessor_with_default(:primary_key, 'id') #:nodoc:
-
- # Gets the prefix for a resource's nested URL (e.g., <tt>prefix/collectionname/1.xml</tt>)
- # This method is regenerated at runtime based on what the prefix is set to.
+
+ # Gets the \prefix for a resource's nested URL (e.g., <tt>prefix/collectionname/1.xml</tt>)
+ # This method is regenerated at runtime based on what the \prefix is set to.
def prefix(options={})
default = site.path
default << '/' unless default[-1..-1] == '/'
@@ -343,14 +349,14 @@ module ActiveResource
prefix(options)
end
- # An attribute reader for the source string for the resource path prefix. This
- # method is regenerated at runtime based on what the prefix is set to.
+ # An attribute reader for the source string for the resource path \prefix. This
+ # method is regenerated at runtime based on what the \prefix is set to.
def prefix_source
prefix # generate #prefix and #prefix_source methods first
prefix_source
end
- # Sets the prefix for a resource's nested URL (e.g., <tt>prefix/collectionname/1.xml</tt>).
+ # Sets the \prefix for a resource's nested URL (e.g., <tt>prefix/collectionname/1.xml</tt>).
# Default value is <tt>site.path</tt>.
def prefix=(value = '/')
# Replace :placeholders with '#{embedded options[:lookups]}'
@@ -376,12 +382,12 @@ module ActiveResource
alias_method :set_collection_name, :collection_name= #:nodoc:
# Gets the element path for the given ID in +id+. If the +query_options+ parameter is omitted, Rails
- # will split from the prefix options.
+ # will split from the \prefix options.
#
# ==== Options
- # +prefix_options+ - A hash to add a prefix to the request for nested URLs (e.g., <tt>:account_id => 19</tt>
+ # +prefix_options+ - A \hash to add a \prefix to the request for nested URLs (e.g., <tt>:account_id => 19</tt>
# would yield a URL like <tt>/accounts/19/purchases.xml</tt>).
- # +query_options+ - A hash to add items to the query string for the request.
+ # +query_options+ - A \hash to add items to the query string for the request.
#
# ==== Examples
# Post.element_path(1)
@@ -471,7 +477,7 @@ module ActiveResource
# ==== Options
#
# * <tt>:from</tt> - Sets the path or custom method that resources will be fetched from.
- # * <tt>:params</tt> - Sets query and prefix (nested URL) parameters.
+ # * <tt>:params</tt> - Sets query and \prefix (nested URL) parameters.
#
# ==== Examples
# Person.find(1)
@@ -519,7 +525,7 @@ module ActiveResource
# Deletes the resources with the ID in the +id+ parameter.
#
# ==== Options
- # All options specify prefix and query parameters.
+ # All options specify \prefix and query parameters.
#
# ==== Examples
# Event.delete(2) # sends DELETE /events/2
@@ -630,8 +636,8 @@ module ActiveResource
attr_accessor :attributes #:nodoc:
attr_accessor :prefix_options #:nodoc:
- # Constructor method for new resources; the optional +attributes+ parameter takes a hash
- # of attributes for the new resource.
+ # Constructor method for \new resources; the optional +attributes+ parameter takes a \hash
+ # of attributes for the \new resource.
#
# ==== Examples
# my_course = Course.new
@@ -647,8 +653,8 @@ module ActiveResource
load(attributes)
end
- # Returns a clone of the resource that hasn't been assigned an +id+ yet and
- # is treated as a new resource.
+ # Returns a \clone of the resource that hasn't been assigned an +id+ yet and
+ # is treated as a \new resource.
#
# ryan = Person.find(1)
# not_ryan = ryan.clone
@@ -683,7 +689,7 @@ module ActiveResource
end
- # A method to determine if the resource a new object (i.e., it has not been POSTed to the remote service yet).
+ # A method to determine if the resource a \new object (i.e., it has not been POSTed to the remote service yet).
#
# ==== Examples
# not_new = Computer.create(:brand => 'Apple', :make => 'MacBook', :vendor => 'MacMall')
@@ -699,12 +705,12 @@ module ActiveResource
id.nil?
end
- # Get the +id+ attribute of the resource.
+ # Gets the <tt>\id</tt> attribute of the resource.
def id
attributes[self.class.primary_key]
end
- # Set the +id+ attribute of the resource.
+ # Sets the <tt>\id</tt> attribute of the resource.
def id=(id)
attributes[self.class.primary_key] = id
end
@@ -745,7 +751,7 @@ module ActiveResource
self == other
end
- # Delegates to id in order to allow two resources of the same type and id to work with something like:
+ # Delegates to id in order to allow two resources of the same type and \id to work with something like:
# [Person.find(1), Person.find(2)] & [Person.find(1), Person.find(4)] # => [Person.find(1)]
def hash
id.hash
@@ -770,9 +776,9 @@ module ActiveResource
end
end
- # A method to save (+POST+) or update (+PUT+) a resource. It delegates to +create+ if a new object,
- # +update+ if it is existing. If the response to the save includes a body, it will be assumed that this body
- # is XML for the final object as it looked after the save (which would include attributes like +created_at+
+ # A method to \save (+POST+) or \update (+PUT+) a resource. It delegates to +create+ if a \new object,
+ # +update+ if it is existing. If the response to the \save includes a body, it will be assumed that this body
+ # is XML for the final object as it looked after the \save (which would include attributes like +created_at+
# that weren't part of the original submit).
#
# ==== Examples
@@ -857,7 +863,7 @@ module ActiveResource
end
end
- # A method to reload the attributes of this object from the remote web service.
+ # A method to \reload the attributes of this object from the remote web service.
#
# ==== Examples
# my_branch = Branch.find(:first)
@@ -872,8 +878,8 @@ module ActiveResource
self.load(self.class.find(to_param, :params => @prefix_options).attributes)
end
- # A method to manually load attributes from a hash. Recursively loads collections of
- # resources. This method is called in +initialize+ and +create+ when a hash of attributes
+ # A method to manually load attributes from a \hash. Recursively loads collections of
+ # resources. This method is called in +initialize+ and +create+ when a \hash of attributes
# is provided.
#
# ==== Examples
@@ -944,7 +950,7 @@ module ActiveResource
end
end
- # Create (i.e., save to the remote service) the new resource.
+ # Create (i.e., \save to the remote service) the \new resource.
def create
returning connection.post(collection_path, encode, self.class.headers) do |response|
self.id = id_from_response(response)
diff --git a/activeresource/lib/active_resource/validations.rb b/activeresource/lib/active_resource/validations.rb
index a7c624f309..4bc906d291 100644
--- a/activeresource/lib/active_resource/validations.rb
+++ b/activeresource/lib/active_resource/validations.rb
@@ -216,39 +216,25 @@ module ActiveResource
end
end
- # Module to allow validation of Active Resource objects, which creates an Errors instance for every resource.
- # Methods are implemented by overriding Base#validate or its variants Each of these methods can inspect
- # the state of the object, which usually means ensuring that a number of attributes have a certain value
- # (such as not empty, within a given range, matching a certain regular expression and so on).
+ # Module to support validation and errors with Active Resource objects. The module overrides
+ # Base#save to rescue ActiveResource::ResourceInvalid exceptions and parse the errors returned
+ # in the web service response. The module also adds an +errors+ collection that mimics the interface
+ # of the errors provided by ActiveRecord::Errors.
#
# ==== Example
#
- # class Person < ActiveResource::Base
- # self.site = "http://www.localhost.com:3000/"
- # protected
- # def validate
- # errors.add_on_empty %w( first_name last_name )
- # errors.add("phone_number", "has invalid format") unless phone_number =~ /[0-9]*/
- # end
+ # Consider a Person resource on the server requiring both a +first_name+ and a +last_name+ with a
+ # <tt>validates_presence_of :first_name, :last_name</tt> declaration in the model:
#
- # def validate_on_create # is only run the first time a new object is saved
- # unless valid_member?(self)
- # errors.add("membership_discount", "has expired")
- # end
- # end
- #
- # def validate_on_update
- # errors.add_to_base("No changes have occurred") if unchanged_attributes?
- # end
- # end
- #
- # person = Person.new("first_name" => "Jim", "phone_number" => "I will not tell you.")
- # person.save # => false (and doesn't do the save)
- # person.errors.empty? # => false
- # person.errors.count # => 2
- # person.errors.on "last_name" # => "can't be empty"
- # person.attributes = { "last_name" => "Halpert", "phone_number" => "555-5555" }
- # person.save # => true (and person is now saved to the remote service)
+ # person = Person.new(:first_name => "Jim", :last_name => "")
+ # person.save # => false (server returns an HTTP 422 status code and errors)
+ # person.valid? # => false
+ # person.errors.empty? # => false
+ # person.errors.count # => 1
+ # person.errors.full_messages # => ["Last name can't be empty"]
+ # person.errors.on(:last_name) # => "can't be empty"
+ # person.last_name = "Halpert"
+ # person.save # => true (and person is now saved to the remote service)
#
module Validations
def self.included(base) # :nodoc:
diff --git a/activesupport/lib/active_support/string_inquirer.rb b/activesupport/lib/active_support/string_inquirer.rb
index 65545748df..cd722a3cfb 100644
--- a/activesupport/lib/active_support/string_inquirer.rb
+++ b/activesupport/lib/active_support/string_inquirer.rb
@@ -1,4 +1,14 @@
module ActiveSupport
+ # Wrapping a string in this class gives you a prettier way to test
+ # for equality. The value returned by <tt>Rails.env</tt> is wrapped
+ # in a StringInquirer object so instead of calling this:
+ #
+ # Rails.env == "production"
+ #
+ # you can call this:
+ #
+ # Rails.env.production?
+ #
class StringInquirer < String
def method_missing(method_name, *arguments)
if method_name.to_s.ends_with?("?")
diff --git a/railties/doc/guides/routing/routing_outside_in.txt b/railties/doc/guides/routing/routing_outside_in.txt
new file mode 100644
index 0000000000..7817fa66d3
--- /dev/null
+++ b/railties/doc/guides/routing/routing_outside_in.txt
@@ -0,0 +1,763 @@
+Rails Routing from the Outside In
+=================================
+
+This guide covers the user-facing features of Rails routing. By referring to this guide, you will be able to:
+
+* Understand the purpose of routing
+* Decipher the code in +routing.rb+
+* Construct your own routes, using either the classic hash style or the now-preferred RESTful style
+* Identify how a route will map to a controller and action
+
+== The Dual Purpose of Routing
+
+Rails routing is a two-way piece of machinery - rather as if you could turn pigs into sausage, and then turn sausage back into pigs. Specifically, it both connects incoming HTTP requests to the code in your application's controllers, and helps you generate URLs without having to hard-code them as strings.
+
+=== Connecting URLs to Code
+
+When your Rails application receives an incoming HTTP request, say
+
+-------------------------------------------------------
+GET /patient/17
+-------------------------------------------------------
+
+the routing engine within Rails is the piece of code that dispatches the request to the appropriate spot in your application. In this case, the application would most likely end up running the +show+ action within the +patients+ controller, displaying the details of the patient whose ID is 17.
+
+=== Generating URLs from Code
+
+Routing also works in reverse. If your application contains this code:
+
+[source, ruby]
+-------------------------------------------------------
+@patient = Patient.find(17)
+<%= link_to "Patient Record", patient_path(@patient) %>
+-------------------------------------------------------
+
+Then the routing engine is the piece that translates that to a link to a URL such as +http://example.com/patient/17+. By using routing in this way, you can reduce the brittleness of your application as compared to one with hard-coded URLs, and make your code easier to read and understand.
+
+== Quick Tour of Routes.rb
+
+There are two components to routing in Rails: the routing engine itself, which is supplied as part of Rails, and the file +config/routes.rb+, which contains the actual routes that will be used by your application. Learning exactly what you can put in +routes.rb+ is the main topic of this guide, but before we dig in let's get a quick overview.
+
+=== Processing the File
+
+In format, +routes.rb+ is nothing more than one big block sent to +ActionController::Routing::Routes.draw+. Within this block, you can have comments, but it's likely that most of your content will be individual lines of code - each line being a route in your application. You'll find five main types of content in this file:
+
+* RESTful Routes
+* Named Routes
+* Nested Routes
+* Regular (old-style) Routes
+* Default Routes
+
+Each of these types of route is covered in more detail later in this guide.
+
+The +routes.rb+ file is processed from top to bottom when a request comes in. The request will be dispatched to the first matching route. If there is no matching route, then Rails returns HTTP status 404 to the caller.
+
+=== RESTful Routes
+
+RESTful routes take advantage of the built-in REST orientation of Rails to wrap up a lot of routing information in a single declaration. A RESTful route looks like this:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :books
+-------------------------------------------------------
+
+=== Named Routes
+
+Named routes give you very readable links in your code, as well as handling incoming requests. Here's a typical named route:
+
+[source, ruby]
+-------------------------------------------------------
+map.login '/login', :controller => 'sessions', :action => 'new'
+-------------------------------------------------------
+
+=== Nested Routes
+
+Nested routes let you declare that one resource is contained within another resource. You'll see later on how this translates to URLs and paths in your code. For example, if your application includes parts, each of which belongs to an assembly, you might have this nested route declaration:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :assemblies do |assemblies|
+ assemblies.resources :parts
+end
+-------------------------------------------------------
+
+=== Regular (old-style) Routes
+
+In many applications, you'll still see the older-style (non-RESTful) routing, which explicitly connects the parts of a URL to a particular action. For example,
+
+[source, ruby]
+-------------------------------------------------------
+map.connect 'parts/:number', :controller => 'inventory', :action => 'show'
+-------------------------------------------------------
+
+=== Default Routes
+
+The default routes are a safety net that catch otherwise-unrouted requests. Many Rails applications will contain this pair of default routes:
+
+[source, ruby]
+-------------------------------------------------------
+map.connect ':controller/:action/:id'
+map.connect ':controller/:action/:id.:format'
+-------------------------------------------------------
+
+These default routes are automatically generated when you create a new Rails application. If you're using RESTful routing, you will probably want to remove them.
+
+== RESTful Routing: the New Default
+
+RESTful routing is the new standard for routing in Rails, and it's the one that you should prefer for new applications. It can take a little while to understand how RESTful routing works, but it's worth the effort; your code will be easier to read and you'll be working with Rails, rather than fighting against it, when you use this style of routing.
+
+=== What is REST?
+
+The foundation of RESTful routing is generally considered to be Roy Fielding's doctoral thesis, link:http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm[Architectural Styles and the Design of Network-based Software Architectures]. Fortunately, you need not read this entire document to understand how REST works in Rails. REST, an acronym for Representational State Transfer, boils down to two main principles for our purposes:
+
+* Using resource identifiers (which, for the purposes of discussion, you can think of as URLs) to represent resources
+* Transferring representations of the state of that resource between system components.
+
+For example, to a Rails application a request such as this:
+
++DELETE /photos/17+
+
+would be understood to refer to a photo resource with the ID of 17, and to indicate a desired action - deleting that resource. REST is a natural style for the architecture of web applications, and Rails makes it even more natural by using conventions to shield you from some of the RESTful complexities.
+
+=== CRUD, Verbs, and Actions
+
+In Rails, a RESTful route provides a mapping between HTTP verbs, controller actions, and (implicitly) CRUD operations in a database. A single entry in the routing file, such as
+
+[source, ruby]
+-------------------------------------------------------
+map.resources photos
+-------------------------------------------------------
+
+creates seven different routes in your application:
+
+[grid="all"]
+`----------`---------------`-----------`--------`-------------------------------------------
+HTTP verb URL controller action used for
+--------------------------------------------------------------------------------------------
+GET /photos Photos index display a list of all photos
+GET /photos/new Photos new return an HTML form for creating a new photo
+POST /photos Photos create create a new photo
+GET /photo/1 Photos show display a specific photo
+GET /photo/1/edit Photos edit return an HTML form for editing a photo
+PUT /photo/1 Photos update update a specific photo
+DELETE /photo/1 Photos destroy delete a specific photo
+--------------------------------------------------------------------------------------------
+
+For the specific routes (those that reference just a single resource), the identifier for the resource will be available within the corresponding controller action as +params[:id]+.
+
+TIP: If you consistently use RESTful routes in your application, you should disable the default routes in +routes.rb+ so that Rails will enforce the mapping between HTTP verbs and routes.
+
+=== URLs and Paths
+
+Creating a RESTful route will also make available a pile of helpers within your application:
+
+* +photos_url+ and +photos_path+ map to the path for the index and create actions
+* +new_photo_url+ and +new_photo_path+ map to the path for the new action
+* +edit_photo_url+ and +edit_photo_path+ map to the path for the edit action
+* +photo_url+ and +photo_path+ map to the path for the show, update, and destroy actions
+
+NOTE: Because routing makes use of the HTTP verb as well as the path in the request to dispatch requests, the seven routes generated by a RESTful routing entry only give rise to four pairs of helpers.
+
+In each case, the +_url+ helper generates a string containing the entire URL that the application will understand, while the +_path+ helper generates a string containing the relative path from the root of the application. For example:
+
+[source, ruby]
+-------------------------------------------------------
+photos_url # => "http://www.example.com/photos"
+photos_path # => "/photos"
+-------------------------------------------------------
+
+=== Singular Resources
+
+You can also apply RESTful routing to singleton resources within your application. In this case, you use +map.resource+ instead of +map.resources+ and the route generation is slightly different. For example, a routing entry of
+
+[source, ruby]
+-------------------------------------------------------
+map.resource geocoder
+-------------------------------------------------------
+
+creates seven different routes in your application:
+
+[grid="all"]
+`----------`---------------`-----------`--------`-------------------------------------------
+HTTP verb URL controller action used for
+--------------------------------------------------------------------------------------------
+GET /geocoder/new Geocoders new return an HTML form for creating the new geocoder
+POST /geocoder Geocoders create create the new geocoder
+GET /geocoder Geocoders show display the one and only geocoder resource
+GET /geocoder/edit Geocoders edit return an HTML form for editing the geocoder
+PUT /geocoder Geocoders update update the one and only geocoder resource
+DELETE /geocoder Geocoders destroy delete the geocoder resource
+--------------------------------------------------------------------------------------------
+
+NOTE: Even though the name of the resource is singular in +routes.rb+, the matching controller is still plural.
+
+A singular RESTful route generates an abbreviated set of helpers:
+
+* +new_geocoder_url+ and +new_geocoder_path+ map to the path for the new action
+* +edit_geocoder_url+ and +edit_geocoder_path+ map to the path for the edit action
+* +geocoder_url+ and +geocoder_path+ map to the path for the create, show, update, and destroy actions
+
+=== Customizing Resources
+
+Although the conventions of RESTful routing are likely to be sufficient for many applications, there are a number of ways to customize the way that RESTful routes work. These options include:
+
+* +:controller+
+* +:singular+
+* +:requirements+
+* +:conditions+
+* +:as+
+* +:path_names+
+* +:path_prefix+
+* +:name_prefix+
+
+You can also add additional routes via the +:member+ and +:collection+ options, which are discussed later in this guide.
+
+==== Using :controller
+
+The +:controller+ option lets you use a controller name that is different from the public-facing resource name. For example, this routing entry:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources photos, :controller => "images"
+-------------------------------------------------------
+
+will recognize incoming URLs containing +photo+ but route the requests to the Images controller:
+
+[grid="all"]
+`----------`---------------`-----------`--------`-------------------------------------------
+HTTP verb URL controller action used for
+--------------------------------------------------------------------------------------------
+GET /photos Images index display a list of all images
+GET /photos/new Images new return an HTML form for creating a new image
+POST /photos Images create create a new image
+GET /photo/1 Images show display a specific image
+GET /photo/1/edit Images edit return an HTML form for editing a image
+PUT /photo/1 Images update update a specific image
+DELETE /photo/1 Images destroy delete a specific image
+--------------------------------------------------------------------------------------------
+
+NOTE: The helpers will be generated with the name of the resource, not the name of the controller. So in this case, you'd still get +photos_path+, +photos_new_path+, and so on.
+
+==== Using :singular
+
+If for some reason Rails isn't doing what you want in converting the plural resource name to a singular name in member routes, you can override its judgment with the +:singular+ option:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :teeth, :singular => "tooth"
+-------------------------------------------------------
+
+TIP: Depending on the other code in your application, you may prefer to add additional rules to the +Inflector+ class instead.
+
+==== Using :requirements
+
+You an use the +:requirements+ option in a RESTful route to impose a format on the implied +:id+ parameter in the singular routes. For example:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources photos, :requirements => {:id => /[A-Z][A-Z][0-9]+/}
+-------------------------------------------------------
+
+This declaration constrains the +:id+ parameter to match the supplied regular expression. So, in this case, +/photos/1+ would no longer be recognized by this route, but +/photos/RR27+ would.
+
+==== Using :conditions
+
+Conditions in Rails routing are currently used only to set the HTTP verb for individual routes. Although in theory you can set this for RESTful routes, in practice there is no good reason to do so. (You'll learn more about conditions in the discussion of old-style routing later in this guide.)
+
+==== Using :as
+
+The +:as+ option lets you override the normal naming for the actual generated paths. For example:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources photos, :as => "images"
+-------------------------------------------------------
+
+will recognize incoming URLs containing +image+ but route the requests to the Photos controller:
+
+[grid="all"]
+`----------`---------------`-----------`--------`-------------------------------------------
+HTTP verb URL controller action used for
+--------------------------------------------------------------------------------------------
+GET /images Photos index display a list of all photos
+GET /images/new Photos new return an HTML form for creating a new photo
+POST /images Photos create create a new photo
+GET /image/1 Photos show display a specific photo
+GET /image/1/edit Photos edit return an HTML form for editing a photo
+PUT /image/1 Photos update update a specific photo
+DELETE /image/1 Photos destroy delete a specific photo
+--------------------------------------------------------------------------------------------
+
+NOTE: The helpers will be generated with the name of the resource, not the path name. So in this case, you'd still get +photos_path+, +photos_new_path+, and so on.
+
+==== Using :path_names
+
+The +:path_names+ option lets you override the automatically-generated "new" and "edit" segments in URLs:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources photos, :path_names => { :new => 'make', :edit => 'change' }
+-------------------------------------------------------
+
+This would cause the routing to recognize URLs such as
+
+-------------------------------------------------------
+/photos/make
+/photos/1/change
+-------------------------------------------------------
+
+NOTE: The actual action names aren't changed by this option; the two URLs show would still route to the new and edit actions.
+
+TIP: If you find yourself wanting to change this option uniformly for all of your routes, you can set a default in your environment:
+
+[source, ruby]
+-------------------------------------------------------
+config.action_controller.resources_path_names = { :new => 'make', :edit => 'change' }
+-------------------------------------------------------
+
+==== Using :path_prefix
+
+The +:path_prefix+ option lets you add additional parameters that will be prefixed to the recognized paths. For example, suppose each photo in your application belongs to a particular photographer. In that case, you might declare this route:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources photos, :path_prefix => '/photographers/:photographer_id'
+-------------------------------------------------------
+
+Routes recognized by this entry would include:
+
+-------------------------------------------------------
+/photographers/1/photo/2
+/photographers/1/photos
+-------------------------------------------------------
+
+NOTE: In most cases, it's simpler to recognize URLs of this sort by creating nested resources, as discussed in the next section.
+
+==== Using :name_prefix
+
+You can use the :name_prefix option to avoid collisions between routes. This is most useful when you have two resources with the same name that use +:path_prefix+ to map differently. For example:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources photos, :path_prefix => '/photographers/:photographer_id', :name_prefix => 'photographer_'
+map.resources photos, :path_prefix => '/agencies/:agency_id', :name_prefix => 'agency_'
+-------------------------------------------------------
+
+This combination will give you route helpers such as +photographer_photos_path+ and +agency_photo_edit_path+ to use in your code.
+
+=== Nested Resources
+
+It's common to have resources that are logically children of other resources. For example, suppose your application includes these models:
+
+[source, ruby]
+-------------------------------------------------------
+class Magazine < ActiveRecord::Base
+ has_many :ads
+end
+
+class Ad < ActiveRecord::Base
+ belongs_to :magazine
+end
+-------------------------------------------------------
+
+Each ad is logically subservient to one magazine. Nested routes allow you to capture this relationship in your routing. In this case, you might include this route declaration:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :magazines do |magazine|
+ magazine.resources :ads
+end
+-------------------------------------------------------
+
+In addition to the routes for magazines, this declaration will also create routes for ads, each of which requires the specification of a magazine in the URL:
+
+[grid="all"]
+`----------`-----------------------`-----------`--------`-------------------------------------------
+HTTP verb URL controller action used for
+--------------------------------------------------------------------------------------------
+GET /magazines/1/ads Ads index display a list of all ads for a specific magazine
+GET /magazines/1/ads/new Ads new return an HTML form for creating a new ad belonging to a specific magazine
+POST /magazines/1/ads Ads create create a new photo belonging to a specific magazine
+GET /magazines/1/ad/1 Ads show display a specific photo belonging to a specific magazine
+GET /magazines/1/ad/1/edit Ads edit return an HTML form for editing a photo belonging to a specific magazine
+PUT /magazines/1/ad/1 Ads update update a specific photo belonging to a specific magazine
+DELETE /magazines/1/ad/1 Ads destroy delete a specific photo belonging to a specific magazine
+--------------------------------------------------------------------------------------------
+
+This will also create routing helpers such as +magazine_ads_url+ and +magazine_edit_ad_path+.
+
+==== Using :name_prefix
+
+The +:name_prefix+ option overrides the automatically-generated prefix in nested route helpers. For example,
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :magazines do |magazine|
+ magazine.resources :ads, :name_prefix => 'periodical'
+end
+-------------------------------------------------------
+
+This will create routing helpers such as +periodical_ads_url+ and +periodical_edit_ad_path+. You can even use +:name_prefix+ to suppress the prefix entirely:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :magazines do |magazine|
+ magazine.resources :ads, :name_prefix => nil
+end
+-------------------------------------------------------
+
+This will create routing helpers such as +ads_url+ and +edit_ad_path+. Note that calling these will still require supplying an article id:
+
+[source, ruby]
+-------------------------------------------------------
+ads_url(@magazine)
+edit_ad_path(@magazine, @ad)
+-------------------------------------------------------
+
+==== Using :has_one and :has_many
+
+The +:has_one+ and +:has_many+ options provide a succinct notation for simple nested routes. Use +:has_one+ to nest a singleton resource, or +:has_many+ to nest a plural resource:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :photos, :has_one => :photographer, :has_many => [:publications, :versions]
+-------------------------------------------------------
+
+This has the same effect as this set of declarations:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :photos do |photo|
+ photo.resource :photographer
+ photo.resources :publications
+ photo.resources :versions
+end
+-------------------------------------------------------
+
+==== Limits to Nesting
+
+You can nest resources within other nested resources if you like. For example:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :publisher do |publisher|
+ publisher.resources :magazine do |magazine|
+ magazine.resources :photos
+ end
+end
+-------------------------------------------------------
+
+However, without the use of +name_prefix => nil+, deeply-nested resources quickly become cumbersome. In this case, for example, the application would recognize URLs such as
+
+-------------------------------------------------------
+/publishers/1/magazines/2/photos/3
+-------------------------------------------------------
+
+The corresponding route helper would be +publisher_magazine_photo_url+, requiring you to specify objects at all three levels.
+
+==== Shallow Nesting
+
+The +:shallow+ option provides an elegant solution to the difficulties of deeply-nested routes. If you specify this option at any level of routing, then paths for nested resources which reference a specific member (that is, those with an +:id+ parameter) will not use the parent path prefix or name prefix. To see what this means, consider this set of routes:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :publisher, :shallow => true do |publisher|
+ publisher.resources :magazine do |magazine|
+ magazine.resources :photos
+ end
+end
+-------------------------------------------------------
+
+This will enable recognition of (among others) these routes:
+
+-------------------------------------------------------
+/publishers/1 ==> publisher_path(1)
+/publishers/1/magazines ==> publisher_magazines_path(1)
+/magazines/2 ==> magazine_path(2)
+/magazines/2/photos ==> magazines_photos_path(2)
+/photos/3 ==> photo_path(3)
+-------------------------------------------------------
+
+=== Adding More RESTful Actions
+
+You are not limited to the seven routes that RESTful routing creates by default. If you like, you may add additional member routes (those which apply to a single instance of the resource), additional new routes (those that apply to creating a new resource), or additional collection routes (those which apply to the collection of resources as a whole).
+
+==== Adding Member Routes
+
+To add a member route, use the +:member+ option:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :photos, :member => { :preview => :get }
+-------------------------------------------------------
+
+This will enable Rails to recognize URLs such as +/photos/1/preview+ using the GET HTTP verb, and route them to the preview action of the Photos controller. It will also create a +preview_photo+ route helper.
+
+Within the hash of member routes, each route name specifies the HTTP verb that it will recognize. You can use +:get+, +:put+, +:post+, +:delete+, or +:any+ here.
+
+==== Adding Collection Routes
+
+To add a collection route, use the +:collection+ option:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :photos, :collection => { :search => :get }
+-------------------------------------------------------
+
+This will enable Rails to recognize URLs such as +/photos/search+ using the GET HTTP verb, and route them to the search action of the Photos controller. It will also create a +search_photos+ route helper.
+
+==== Adding New Routes
+
+To add a new route (one that creates a new resource), use the +:new+ option:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :photos, :new => { :upload => :post }
+-------------------------------------------------------
+
+This will enable Rails to recognize URLs such as +/photos/upload+ using the POST HTTP verb, and route them to the upload action of the Photos controller. It will also create a +upload_photos+ route helper.
+
+TIP: If you want to redefine the verbs accepted by one of the standard actions, you can do so by explicitly mapping that action. For example:
+
+[source, ruby]
+-------------------------------------------------------
+map.resources :photos, :new => { :new => :any }
+-------------------------------------------------------
+
+This will allow the new action to be invoked by any request to +photos/new+, no matter what HTTP verb you use.
+
+==== A Note of Caution
+
+If you find yourself adding many extra actions to a RESTful route, it's time to stop and ask yourself whether you're disguising the presence of another resource that would be better split off on its own. When the +:member+ and +:collection+ hashes become a dumping-ground, RESTful routes lose the advantage of easy readability that is one of their strongest points.
+
+== Regular (Old-Style) Routes
+
+Before there was RESTful routing, there was simple Rails routing - a way to map URLs to controllers and actions. With regular routing, you don't get the masses of routes automatically generated by RESTful routing. Instead, you must set up each route within your application separately.
+
+While RESTful routing has become the Rails standard, there are still plenty of places where the simpler regular routing works fine. You can even mix the two styles within a single application.
+
+=== Bound Parameters
+
+When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. Two of these symbols are special: +:controller+ maps to the name of a controller in your application, and +:action+ maps to the name of an action within that controller. For example, consider one of the default Rails routes:
+
+[source, ruby]
+-------------------------------------------------------
+map.connect ':controller/:action/:id'
+-------------------------------------------------------
+
+If an incoming request of +/photos/show/1+ is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke the +show+ action of the +Photos+ controller, and to make the final parameter (1) available as +params[:id]+.
+
+=== Wildcard Components
+
+You can set up as many wildcard symbols within a regular route as you like. Anything other than +:controller+ or +:action+ will be available to the matching action as part of the params hash. So, if you set up this route:
+
+[source, ruby]
+-------------------------------------------------------
+map.connect ':controller/:action/:id/:userid:'
+-------------------------------------------------------
+
+An incoming URL of +/photos/show/1/2+ will be dispatched to the +show+ action of the +Photos+ controller. +params[:id]+ will be set to 1, and +params[:user_id]+ will be set to 2.
+
+=== Static Text
+
+You can specify static text when creating a route. In this case, the static text is used only for matching the incoming requests:
+
+[source, ruby]
+-------------------------------------------------------
+map.connect ':controller/:action/:id/with_user/:userid:'
+-------------------------------------------------------
+
+This route would respond to URLs such as +/photos/show/1/with_user/2+.
+
+=== Querystring Parameters
+
+Rails routing automatically picks up querystring parameters and makes them available in the +params+ hash. For example, with this route:
+
+[source, ruby]
+-------------------------------------------------------
+map.connect ':controller/:action/:id'
+-------------------------------------------------------
+
+An incoming URL of +/photos/show/1?user_id=2+ will be dispatched to the +show+ action of the +Photos+ controller. +params[:id]+ will be set to 1, and +params[:user_id]+ will be equal to 2.
+
+=== Defining Defaults
+
+You do not need to explicitly use the +:controller+ and +:action+ symbols within a route. You can supply defaults for these two parameters in a hash:
+
+[source, ruby]
+-------------------------------------------------------
+map.connect 'photo/:id', :controller => 'photos', :action => 'show'
+-------------------------------------------------------
+
+With this route, an incoming URL of +/photos/12+ would be dispatched to the +show+ action within the +Photos+ controller.
+
+=== Named Routes
+
+Regular routes need not use the +connect+ method. You can use any other name here to create a _named route_. For example,
+
+[source, ruby]
+-------------------------------------------------------
+map.logout '/logout', :controller => 'sessions', :action => 'destroy'
+-------------------------------------------------------
+
+This will do two things. First, requests to +/logout+ will be sent to the +destroy+ method of the +Sessions+ controller. Second, Rails will maintain the +logout_path+ and +logout_url+ helpers for use within your code.
+
+=== Route Requirements
+
+You can use the +:requirements+ option to enforce a format for any parameter in a route:
+
+[source, ruby]
+-------------------------------------------------------
+map.connect 'photo/:id', :controller => 'photos', :action => 'show',
+ :requirements => { :id => /[A-Z]\d{5}/ }
+-------------------------------------------------------
+
+This route would respond to URLs such as +/photo/A12345+. You can more succinctly express the same route this way:
+
+[source, ruby]
+-------------------------------------------------------
+map.connect 'photo/:id', :controller => 'photos', :action => 'show',
+ :id => /[A-Z]\d{5}/
+-------------------------------------------------------
+
+=== Route Conditions
+
+Route conditions (introduced with the +:conditions+ option) are designed to implement restrictions on routes. Currently, the only supported restriction is +:method+:
+
+[source, ruby]
+-------------------------------------------------------
+map.connect 'photo/:id', :controller => 'photos', :action => 'show',
+ :conditions => { :method => :get }
+-------------------------------------------------------
+
+As with conditions in RESTful routes, you can specify +:get+, +:post+, +:put+, +:delete+, or +:any+ for the acceptable method.
+
+=== Route Globbing
+
+Route globbing is a way to specify that a particular parameter (which must be the last parameter in the route) should engulf all the remaining parts of a route. For example
+
+[source, ruby]
+-------------------------------------------------------
+map.connect 'photo/*other', :controller => 'photos', :action => 'unknown',
+-------------------------------------------------------
+
+This route would match +photo/12+ or +/photo/long/path/to/12+ equally well, creating an array of path segments as the value of +params[:other]+.
+
+=== Route Options
+
+You can use +:with_options+ to simplify defining groups of similar routes:
+
+[source, ruby]
+-------------------------------------------------------
+map.with_options :controller => 'photo' do |photo|
+ photo.list '', :action => 'index'
+ photo.delete ':id/delete', :action => 'delete'
+ photo.edit ':id/edit', :action => 'edit'
+end
+-------------------------------------------------------
+
+The importance of +map.with_options+ has declined with the introduction of RESTful routes.
+
+== Formats and respond_to
+
+There's one more way in which routing can do different things depending on differences in the incoming HTTP request: by issuing a response that corresponds to what the request specifies that it will accept. In Rails routing, you can control this with the special +:format+ parameter in the route.
+
+For instance, consider the second of the default routes in the boilerplate +routes.rb+ file:
+
+[source, ruby]
+-------------------------------------------------------
+map.connect ':controller/:action/:id.:format'
+-------------------------------------------------------
+
+This route matches requests such as +/photo/new/1.xml+ or +/photo/show/2.rss+. Within the appropriate action code, you can issue different responses depending on the requested format:
+
+[source, ruby]
+-------------------------------------------------------
+respond_to do |format|
+ format.html # return the default template for HTML
+ format.xml { render :xml => @photo.to_xml }
+end
+-------------------------------------------------------
+
+=== Specifying the Format with an HTTP Header
+
+If there is no +:format+ parameter in the route, Rails will automatically look at the HTTP Accept header to determine the desired format.
+
+=== Recognized MIME types
+
+By default, Rails recognizes +html+, +text+, +json+, +csv+, +xml+, +rss+, +atom+, and +yaml+ as acceptable response types. If you need types beyond this, you can register them in your environment:
+
+[source, ruby]
+-------------------------------------------------------
+Mime::Type.register "image/jpg", :jpg
+-------------------------------------------------------
+
+== The Default Routes
+
+When you create a new Rails application, +routes.rb+ is initialized with two default routes:
+
+[source, ruby]
+-------------------------------------------------------
+map.connect ':controller/:action/:id'
+map.connect ':controller/:action/:id.:format'
+-------------------------------------------------------
+
+These routes provide reasonable defaults for many URLs, if you're not using RESTful routing.
+
+NOTE: The default routes will make every action of every controller in your application accessible to GET requests. If you've designed your application to make consistent use of RESTful and named routes, you should comment out the default routes.
+
+== The Empty Route
+
+Don't confuse the default routes with the empty route. The empty route has one specific purpose: to route requests that come in to the root of the web site. For example, if your site is example.com, then requests to +http://example.com+ or +http://example.com/+ will be handled by the empty route.
+
+=== Using map.root
+
+The preferred way to set up the empty route is with the +map.root+ command:
+
+[source, ruby]
+-------------------------------------------------------
+map.root :controller => "pages", :action => "main"
+-------------------------------------------------------
+
+The use of the +root+ method tells Rails that this route applies to requests for the root of the site.
+
+For better readability, you can specify an already-created route in your call to +map.root+:
+
+[source, ruby]
+-------------------------------------------------------
+map.index :controller => "pages", :action => "main"
+map.root :index
+-------------------------------------------------------
+
+Because of the top-down processing of the file, the named route must be specified _before_ the call to +map.route+.
+
+=== Connecting the Empty String
+
+You can also specify an empty route by explicitly connecting the empty string:
+
+[source, ruby]
+-------------------------------------------------------
+map.connect '', :controller => "pages", :action => "main"
+-------------------------------------------------------
+
+TIP: If the empty route does not seem to be working in your application, make sure that you have deleted the file +public/index.html+ from your Rails tree.
+
+== Dumping Routes with rake
+
+If you want a complete list of all of the available routes in your application, run the +rake routes+ command. This will dump all of your routes to the console, in the same order that they appear in +routes.rb+. For each route, you'll see:
+
+* The route name (if any)
+* The HTTP verb used (if the route doesn't respond to all verbs)
+* The URL pattern
+* The routing parameters that will be generated by this URL
+
+For example, here's a small section of the +rake routes+ output for a RESTful route:
+
+-------------------------------------------------------------------------------------------------------
+ users GET /users {:controller=>"users", :action=>"index"}
+formatted_users GET /users.:format {:controller=>"users", :action=>"index"}
+ POST /users {:controller=>"users", :action=>"create"}
+ POST /users.:format {:controller=>"users", :action=>"create"}
+-------------------------------------------------------------------------------------------------------
+
+TIP: You'll find that the output from +rake routes+ is much more readable if you widen your terminal window until the output lines don't wrap.
diff --git a/railties/environments/environment.rb b/railties/environments/environment.rb
index 2140dfe971..abdb863130 100644
--- a/railties/environments/environment.rb
+++ b/railties/environments/environment.rb
@@ -63,5 +63,6 @@ Rails::Initializer.run do |config|
# config.active_record.schema_format = :sql
# Activate observers that should always be running
- # config.active_record.observers = :cacher, :garbage_collector
+ # Please note that observers generated using script/generate observer need to have an _observer suffix
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
end
diff --git a/railties/lib/commands/dbconsole.rb b/railties/lib/commands/dbconsole.rb
index 5be3b5dd8e..6ff895aa30 100644
--- a/railties/lib/commands/dbconsole.rb
+++ b/railties/lib/commands/dbconsole.rb
@@ -6,7 +6,7 @@ include_password = false
OptionParser.new do |opt|
opt.banner = "Usage: dbconsole [options] [environment]"
- opt.on("-p", "--include-password", "Automatically provide the database from database.yml") do |v|
+ opt.on("-p", "--include-password", "Automatically provide the password from database.yml") do |v|
include_password = true
end
opt.parse!(ARGV)