diff options
author | Pratik Naik <pratiknaik@gmail.com> | 2008-09-03 17:58:47 +0100 |
---|---|---|
committer | Pratik Naik <pratiknaik@gmail.com> | 2008-09-03 17:58:47 +0100 |
commit | 6ef35461dc7148ce37ed602d65a24f6c883fd044 (patch) | |
tree | c190505eaa8b98b4fcae4403bdd4776957d07785 | |
parent | 10fe6a6d8940300dd6698ec38e9c9573404e687d (diff) | |
download | rails-6ef35461dc7148ce37ed602d65a24f6c883fd044.tar.gz rails-6ef35461dc7148ce37ed602d65a24f6c883fd044.tar.bz2 rails-6ef35461dc7148ce37ed602d65a24f6c883fd044.zip |
Merge docrails
23 files changed, 312 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/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) |