Browse files

Merge docrails

  • Loading branch information...
1 parent 10fe6a6 commit 6ef35461dc7148ce37ed602d65a24f6c883fd044 @lifo lifo committed Sep 3, 2008
View
4 actionpack/lib/action_controller/caching/actions.rb
@@ -38,8 +38,8 @@ module Caching
# 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.
View
69 actionpack/lib/action_controller/request.rb
@@ -22,7 +22,7 @@ def self.relative_url_root=(*args)
# 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 @@ def request_method
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,34 +59,36 @@ def delete?
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
memoize :content_length
# 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 @@ def fresh?(response)
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 @@ def format
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 @@ def format=(extension)
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 @@ def xml_http_request?
# 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 @@ def server_software
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 @@ def ssl?
@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 @@ def host
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,38 +288,39 @@ def port
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
else 80
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)
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)
parts = host.split('.')
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 @@ def query_string
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 @@ def request_uri
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 @@ def path
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 @@ def raw_post
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 @@ def path_parameters=(parameters) #:nodoc:
@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
View
2 actionpack/lib/action_controller/rescue.rb
@@ -148,7 +148,7 @@ def log_error(exception) #:doc:
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
View
58 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 @@ def initialize(entity, options)
end
# Creates named routes for implementing verb-oriented controllers
- # for a collection resource.
+ # for a collection \resource.
#
# For example:
#
@@ -252,20 +252,20 @@ def initialize(entity, options)
# 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 @@ def initialize(entity, options)
#
# * <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 @@ def initialize(entity, options)
# 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 @@ def initialize(entity, options)
#
# 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:
#
View
4 actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -155,10 +155,10 @@ def hidden_field_tag(name, value = nil, options = {})
# 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.
View
2 actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -614,7 +614,7 @@ def include_helpers_from_context
# 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|
View
2 actionpack/lib/action_view/helpers/text_helper.rb
@@ -507,7 +507,7 @@ def cycle(first_value, *values)
# @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")
View
4 activemodel/lib/active_model/validations/uniqueness.rb
@@ -25,7 +25,7 @@ module ClassMethods
# 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 @@ def validates_uniqueness_of(*attr_names)
end
end
end
-end
+end
View
15 activerecord/lib/active_record/associations.rb
@@ -660,8 +660,8 @@ module ClassMethods
#
# === 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 @@ def destroy_without_callbacks
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}"
View
36 activerecord/lib/active_record/associations/association_collection.rb
@@ -2,6 +2,19 @@
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 @@ def create!(attrs = {})
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 @@ def size
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
View
57 activerecord/lib/active_record/associations/association_proxy.rb
@@ -39,7 +39,7 @@ module Associations
# 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 @@ def initialize(owner, reflection)
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 @@ def interpolate_sql(sql, record = nil)
@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 @@ def set_belongs_to_association_for(record)
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 @@ def merge_options_from_reflection!(options)
)
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 @@ def method_missing(method, *args)
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,24 +228,31 @@ def load_target
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})"
raise ActiveRecord::AssociationTypeMismatch, message
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
View
14 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 @@ def owner_quoted_id
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)
View
61 activerecord/lib/active_record/base.rb 100644 → 100755
@@ -500,7 +500,7 @@ class << self # Class methods
# * <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 @@ def destroy(id)
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 @@ def update_all(updates, conditions = nil, options = {})
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 @@ def destroy_all(conditions = nil)
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 @@ def destroy_all(conditions = nil)
#
# 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 @@ def new_record?
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
View
4 activerecord/lib/active_record/calculations.rb
@@ -14,7 +14,7 @@ module ClassMethods
#
# 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 @@ def sum(column_name, options = {})
# 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.
View
10 activerecord/lib/active_record/callbacks.rb
@@ -3,7 +3,7 @@
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 @@ def self.included(base) #:nodoc:
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 @@ def create_or_update_with_callbacks #:nodoc:
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 @@ def create_with_callbacks #:nodoc:
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:
View
26 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 @@ def scopes
# 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 @@ def scopes
# 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 @@ def scopes
#
# 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 @@ def scopes
# 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
View
2 activerecord/lib/active_record/transactions.rb
@@ -64,7 +64,7 @@ def self.included(base)
#
# 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
#
View
2 activerecord/lib/active_record/validations.rb
@@ -619,7 +619,7 @@ def validates_length_of(*attrs)
# 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
View
80 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 @@ def site=(site)
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 @@ def user
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 @@ def password
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 @@ def timeout
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 @@ def headers
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 @@ def prefix(options={})
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 @@ def prefix(options={}) "#{prefix_call}" end
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 @@ def create(attributes = {})
# ==== 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 @@ def find(*arguments)
# 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 @@ def split_options(options = {})
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 @@ def initialize(attributes = {})
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 @@ def clone
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 @@ def new?
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 @@ def eql?(other)
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 @@ def dup
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 @@ def encode(options={})
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 @@ def reload
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 @@ def update
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)
View
44 activeresource/lib/active_resource/validations.rb
@@ -216,39 +216,25 @@ def from_xml(xml)
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:
View
10 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?("?")
View
3 railties/environments/environment.rb
@@ -63,5 +63,6 @@
# 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
View
2 railties/lib/commands/dbconsole.rb
@@ -6,7 +6,7 @@
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)

0 comments on commit 6ef3546

Please sign in to comment.